Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,102 changes: 2,102 additions & 0 deletions compile_commands.json

Large diffs are not rendered by default.

105 changes: 104 additions & 1 deletion src/dev/esp32/lanbonl8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

int16_t PulseCounter = 0; // pulse counter, max. value is 32535
int OverflowCounter = 0; // pulse counter overflow counter
uint32_t pulseOffset = 0; // total historical pulses, used to calculate total energy consumption across power cycles
uint32_t totalPulses;

pcnt_isr_handle_t user_isr_handle = NULL; // interrupt handler - not used
Expand All @@ -46,9 +47,96 @@ esp_adc_cal_characteristics_t* adc_chars =
new esp_adc_cal_characteristics_t; // adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));

int16_t watt_10 = 0;
//int16_t kwh_10 = 0;
float kwh = 0;

namespace dev {

static void energy_save()
{
Preferences preferences;
if (nvs_user_begin(preferences, "energy", false)){
preferences.putUInt("pulses", totalPulses + pulseOffset);
preferences.end();
}
}

static void energy_restore()
{
Preferences preferences;
if (nvs_user_begin(preferences, "energy", true)){
pulseOffset = preferences.getUInt("pulses", 0);
preferences.end();
}
}

static void moodlight_save(moodlight_t& ml)
{
Preferences preferences;
if(nvs_user_begin(preferences, "moodlight", false)) {
preferences.putUChar("brightness", ml.brightness);
preferences.putUChar("power", ml.power);
preferences.putBytes("rgbww", ml.rgbww, sizeof(ml.rgbww));
preferences.end();
}
}

static void moodlight_restore(moodlight_t& ml)
{
Preferences preferences;
if(nvs_user_begin(preferences, "moodlight", true)) {
ml.brightness = preferences.getUChar("brightness", 255);
ml.power = preferences.getUChar("power", 0);
preferences.getBytes("rgbww", ml.rgbww, sizeof(ml.rgbww));
preferences.end();
}
}

static void backlight_save(uint8_t level, bool power)
{
Preferences preferences;
if(nvs_user_begin(preferences, "backlight", false)) {
preferences.putUChar("level", level);
preferences.putBool("power", power);
preferences.end();
}
}

static void backlight_restore(uint8_t& level, bool& power)
{
Preferences preferences;
if(nvs_user_begin(preferences, "backlight", true)) {
level = preferences.getUChar("level", 255);
power = preferences.getBool("power", true);
preferences.end();
}
}

void LanbonL8::set_backlight_level(uint8_t level)
{
Esp32Device::set_backlight_level(level);
backlight_save(level, get_backlight_power());
}

void LanbonL8::set_backlight_power(bool power)
{
Esp32Device::set_backlight_power(power);
backlight_save(get_backlight_level(), power);
}

void LanbonL8::energy_reset()
{
pulseOffset = 0;
totalPulses = 0;
OverflowCounter = 0;
pcnt_counter_clear(PCNT_FREQ_UNIT);
Preferences preferences;
if(nvs_user_begin(preferences, "energy", false)) {
preferences.putUInt("pulses", 0);
preferences.end();
}
}

static void check_efuse(void)
{

Expand Down Expand Up @@ -120,6 +208,14 @@ void energy_pulse_counter_init()
void LanbonL8::init()
{
energy_pulse_counter_init();
energy_restore();

// Restore backlight state
uint8_t level = 255;
bool power = true;
backlight_restore(level, power);
Esp32Device::set_backlight_level(level);
Esp32Device::set_backlight_power(power);

// Check if Two Point or Vref are burned into eFuse
check_efuse();
Expand All @@ -139,7 +235,13 @@ void LanbonL8::loop_5s()
uint32_t delta = newPulses - totalPulses;
totalPulses = newPulses;
watt_10 = DEC / 5 * delta * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND;
int16_t kwh_10 = DEC * totalPulses * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND / 3600 / 1000;
//kwh_10 = DEC * totalPulses * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND / 3600 / 1000;
kwh = (float)((totalPulses + pulseOffset) * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND / 3600.0f / 1000.0f);

if (++_save_counter >= 720){ //trigger hourly
_save_counter = 0;
energy_save();
}
// LOG_VERBOSE(TAG_DEV, F("Pulse Counter %d.%d W / %d / %d.%d kWh"), watt_10 / DEC, watt_10 % DEC, totalPulses,
// kwh_10 / DEC, kwh_10 % DEC);
// uint32_t temp = (temprature_sens_read() - 32) * 100 / 1.8;
Expand All @@ -156,6 +258,7 @@ void LanbonL8::get_sensors(JsonDocument& doc)

/* Pulse counter Stats */
sensor[F("Power")] = serialized(String(1.0f * watt_10 / DEC, 2));
sensor[F("Total")] = serialized(String(kwh, 3));
}

//------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/dev/esp32/lanbonl8.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class LanbonL8 : public Esp32Device {
void init();
void loop_5s();
void get_sensors(JsonDocument& doc);
void energy_reset();
void set_backlight_level(uint8_t level);
void set_backlight_power(bool power);
private:
uint16_t _save_counter = 0;
};

} // namespace dev
Expand Down
14 changes: 12 additions & 2 deletions src/hasp/hasp_dispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ uint16_t dispatchSecondsToNextTeleperiod = 0;
uint16_t dispatchSecondsToNextSensordata = 0;
uint16_t dispatchSecondsToNextDiscovery = 0;
uint8_t nCommands = 0;
haspCommand_t commands[29];
haspCommand_t commands[32];

moodlight_t moodlight = {.brightness = 255};
uint8_t saved_jsonl_page = 0;
Expand Down Expand Up @@ -95,6 +95,14 @@ void dispatch_state_subtopic(const char* subtopic, const char* payload)
#endif
}

#if defined (LANBONL8)
void dispatch_energy_reset(const char*, const char*, uint8_t source)
{
haspDevice.energy_reset();
LOG_WARNING(TAG_MSGR, F("Energy reset"));
}
#endif

void dispatch_state_eventid(const char* topic, hasp_event_t eventid)
{
char payload[32];
Expand Down Expand Up @@ -1711,7 +1719,9 @@ void dispatchSetup()
dispatch_add_command(PSTR("setupap"), oobeFakeSetup);
#endif
/* WARNING: remember to expand the commands array when adding new commands */

#if defined(LANBONL8)
dispatch_add_command(PSTR("energy_reset"), dispatch_energy_reset);
#endif
LOG_INFO(TAG_MSGR, F(D_SERVICE_STARTED));
}

Expand Down
4 changes: 4 additions & 0 deletions src/hasp/hasp_nvs.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* MIT License - Copyright (c) 2019-2024 Francis Van Roie
For full license information read the LICENSE file in the project folder */

#include "Preferences.h"
#include "pgmspace.h"
#include "sys/gpio/hasp_gpio.h"
#include <cstdio>
#ifdef ESP32

#include "hasplib.h"
Expand Down
68 changes: 65 additions & 3 deletions src/sys/gpio/hasp_gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,16 @@ hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG] = {
// {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW},
};
uint8_t pwm_channel = 1; // Backlight has 0
#ifdef LANBONL8
static bool gpio_restoring = false;
#endif

static inline void gpio_input_event(uint8_t pin, hasp_event_t eventid);

static inline bool gpio_set_digital_value(hasp_gpio_config_t* gpio);

static inline bool gpio_is_output(hasp_gpio_config_t* gpio);

static inline void gpio_update_group(uint8_t group, lv_obj_t* obj, bool power, int32_t val, int32_t min, int32_t max)
{
hasp_update_value_t value = {.obj = obj, .group = group, .min = min, .max = max, .val = val, .power = power};
Expand Down Expand Up @@ -111,6 +118,33 @@ class CapacitiveConfig : public ButtonConfig {
CapacitiveConfig touchConfig; // Capacitive touch
#endif

#ifdef LANBONL8
static void gpio_save_output_state(hasp_gpio_config_t* gpio)
{
if (gpio_restoring) return;
Preferences preferences;
char key[8];
snprintf(key, sizeof(key), "p%d", gpio->pin);

if(nvs_user_begin(preferences, "gpio", false)) {
bool result = preferences.putBool(key, gpio->power);
preferences.end();
}
}

static void gpio_restore_output_state(hasp_gpio_config_t* gpio)
{
Preferences preferences;
char key[8];
snprintf(key, sizeof(key), "p%d", gpio->pin);
if(nvs_user_begin(preferences, "gpio", true)) {
bool val = preferences.getBool(key, gpio->inverted);
gpio->power = val;
preferences.end();
}
}
#endif

void gpio_log_serial_dimmer(const char* command)
{
char buffer[32];
Expand Down Expand Up @@ -277,9 +311,14 @@ static void gpio_setup_pin(uint8_t index)
case hasp_gpio_type_t::POWER_RELAY:
case hasp_gpio_type_t::LIGHT_RELAY:
pinMode(gpio->pin, OUTPUT);
#ifdef LANBONL8
gpio_restore_output_state(gpio);
#else
gpio->power = gpio->inverted; // gpio is off, state is set to reflect the true output state of the gpio
#endif
gpio->max = 1; // on-off
gpio->val = gpio->power;
gpio_set_digital_value(gpio);
break;

case hasp_gpio_type_t::PWM:
Expand Down Expand Up @@ -350,6 +389,27 @@ void gpioSetup()
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
gpio_setup_pin(i);
}

#ifdef LANBONL8
// Restore UI state for all relay outputs after boot
gpio_restoring = true;
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
hasp_gpio_config_t* gpio = &gpioConfig[i];
if(gpio->group && gpio_is_output(gpio)) {
hasp_update_value_t value = {
.obj = NULL,
.group = gpio->group,
.min = 0,
.max = 1,
.val = gpio->power,
.power = gpio->power
};
dispatch_normalized_group_values(value);
}
}
gpio_restoring = false;
#endif

moodlight_t moodlight = {.brightness = 255};
gpio_set_moodlight(moodlight);

Expand Down Expand Up @@ -533,10 +593,9 @@ static inline bool gpio_set_digital_value(hasp_gpio_config_t* gpio)

#if defined(ARDUINO_ARCH_ESP32)
digitalWrite(gpio->pin, state);
return true; // sent

return true;
#else
return false; // not implemented
return false;
#endif
}

Expand Down Expand Up @@ -607,6 +666,9 @@ static bool gpio_set_output_value(hasp_gpio_config_t* gpio, bool power, uint16_t
switch(gpio->type) {
case hasp_gpio_type_t::POWER_RELAY:
case hasp_gpio_type_t::LIGHT_RELAY:
#ifdef LANBONL8
gpio_save_output_state(gpio);
#endif
return gpio_set_digital_value(gpio);

case hasp_gpio_type_t::LED... hasp_gpio_type_t::LED_W:
Expand Down