Skip to content

Commit

Permalink
read configuartion from flash; fix downgradability
Browse files Browse the repository at this point in the history
  • Loading branch information
root committed Jun 7, 2024
1 parent 1f201c8 commit 6b9ad0f
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 24 deletions.
22 changes: 21 additions & 1 deletion mos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ config_schema:
- ["ssw.name", "s", "", {}]
- ["ssw.in_mode", "i", 0, {}]

#abstract for calibration type
- ["gains", "o", {title: "", abstract: true}]
- ["gains.avgain", "f", 4194304, {title: ""}] #default register values are 0x40000
- ["gains.aigain", "f", 4194304, {title: ""}]
- ["gains.awgain", "f", 4194304, {title: ""}]
- ["gains.phcala", "f", 0, {title: "Sign magnitude 10bit value. register is 16 bit, value coming from cal seems to have sign in 22 bit (1 << 22)"}]
- ["gains.bvgain", "f", 4194304, {title: ""}]
- ["gains.bigain", "f", 4194304, {title: ""}]
- ["gains.bwgain", "f", 4194304, {title: ""}]
- ["gains.phcalb", "f", 0, {title: ""}]

build_vars:
# BLE disabled for most models.
MGOS_HAP_BLE: 0
Expand Down Expand Up @@ -697,7 +708,7 @@ conds:
MGOS_ROOT_FS_TYPE: LFS
MGOS_ROOT_FS_SIZE: 458752
ESP_IDF_EXTRA_PARTITION: "aux,0x55,0x00,0x3f0000,48K"
ESP_IDF_EXTRA_PARTITION_2: "shelly,data,0x88,0x3fc000,16K"
ESP_IDF_EXTRA_PARTITION_2: "shelly,data,0x88,0x3fc000,16K,encrypted"
ESP_IDF_SDKCONFIG_OPTS: >
${build_vars.ESP_IDF_SDKCONFIG_OPTS}
CONFIG_FREERTOS_UNICORE=y
Expand Down Expand Up @@ -738,6 +749,15 @@ conds:
- ["ssw2", "ssw", {title: "SSW2 settings"}]
- ["ssw2.name", "Input 2"]

#factory config saved at 0x1000 in shelly partition
- ["factory", "o", {title: ""}]
- ["factory.batch", "s", "", {title: ""}]
- ["factory.model", "s", "", {title: ""}]
- ["factory.version", "i", 0, {title: ""}]
- ["factory.calib", "o", {title: "Factory calib settings"}]
- ["factory.calib.done", "b", false, {title: ""}]
- ["factory.calib.gains0", "gains", {title: ""}]

- when: build_vars.MODEL == "ShellyPlusI4"
apply:
name: PlusI4
Expand Down
157 changes: 134 additions & 23 deletions src/ShellyPlus2PM/shelly_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "shelly_temp_sensor_ntc.hpp"
#include "shelly_temp_sensor_ow.hpp"

#include "esp_partition.h"

#include <algorithm>

#include "shelly_hap_garage_door_opener.hpp"
Expand All @@ -40,6 +42,58 @@ static std::vector<std::unique_ptr<TempSensor>> sensors;

static struct mgos_ade7953 *s_ade7953 = NULL;

#define MGOS_ADE7953_REG_AIGAIN 0x380
#define MGOS_ADE7953_REG_AVGAIN 0x381
#define MGOS_ADE7953_REG_AWGAIN 0x382
#define MGOS_ADE7953_REG_BVGAIN 0x38D
#define MGOS_ADE7953_REG_BWGAIN 0x38E
#define MGOS_ADE7953_REG_BIGAIN 0x38C

static void ReadFactoryData(mgos_config *c) {
const char *label = "shelly";
esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_ANY;
esp_partition_type_t type = ESP_PARTITION_TYPE_ANY;

const esp_partition_t *part = esp_partition_find_first(type, subtype, label);
if (part == NULL) {
LOG(LL_INFO, ("Partition %s not found", label));
return;
}

size_t part_offset = 0x0;
size_t size = 0x2000; // map both "partitions"
spi_flash_mmap_handle_t out_handle;
const void *out_ptr;

esp_err_t err = esp_partition_mmap(
part, part_offset, size, SPI_FLASH_MMAP_DATA, &out_ptr, &out_handle);
if (err) {
LOG(LL_INFO, ("Partition %s not mapped", label));
return;
}

// read first partition at 0x0
const struct mg_str str = mg_mk_str_n((const char *) out_ptr, size);
bool succ = mgos_conf_parse_sub(str, mgos_config_get_schema(),
c); // TODO: merge into main cfg
if (!succ) {
LOG(LL_INFO, ("Partition %s not parsed", "factory data"));
return;
}

// read escond partition at 0x1000
void *ptr2 = (uint8_t *) out_ptr + 0x1000;
const struct mg_str str2 = mg_mk_str_n((const char *) ptr2, size);
succ = mgos_conf_parse_sub(str2, mgos_config_get_schema(),
c); // TODO: merge into main cfg
if (!succ) {
LOG(LL_INFO, ("Partition %s not parsed", "factory calib"));
return;
}

spi_flash_munmap(out_handle);
}

static Status PowerMeterInit(std::vector<std::unique_ptr<PowerMeter>> *pms) {
const struct mgos_config_ade7953 ade7953_cfg = {
.voltage_scale = .0000382602,
Expand All @@ -52,21 +106,60 @@ static Status PowerMeterInit(std::vector<std::unique_ptr<PowerMeter>> *pms) {
.apower_scale_1 = (1 / 164.0),
.aenergy_scale_0 = (1 / 25240.0),
.aenergy_scale_1 = (1 / 25240.0),
.voltage_pga_gain = 0,
.current_pga_gain_0 = 0,
.current_pga_gain_1 = 0,
.voltage_pga_gain = 0, //MGOS_ADE7953_PGA_GAIN_2,
.current_pga_gain_0 = 0, //MGOS_ADE7953_PGA_GAIN_8,
.current_pga_gain_1 = 0, //MGOS_ADE7953_PGA_GAIN_8,
};

int reset_pin = 33;
mgos_config_factory *c = &(mgos_sys_config.factory);

int reset_pin = -1;
if (c->model != NULL && strcmp(c->model, "SNSW-102P16EU") == 0) {
LOG(LL_INFO, ("model %s", c->model));
LOG(LL_INFO, ("Newer revision detected"));
if (mgos_sys_config_get_i2c_sda_gpio() != 26) {
mgos_sys_config_set_i2c_sda_gpio(26);
}
reset_pin = 33;
} else {
if (mgos_sys_config_get_i2c_sda_gpio() != 33) {
mgos_sys_config_set_i2c_sda_gpio(33);
}
reset_pin = 0; // unknown?
}
// we need to reboot if we changed because i2c_global was already called; this
// messes up the downgrading process in original firmware
//
mgos_gpio_setup_output(reset_pin, 0);
mgos_usleep(10);
mgos_gpio_setup_output(reset_pin, 1);
mgos_msleep(10);

s_ade7953 = mgos_ade7953_create(mgos_i2c_get_global(), &ade7953_cfg);

if (s_ade7953 == nullptr) {
LOG(LL_INFO, ("Failed to init ADE7953"));

return mgos::Errorf(STATUS_UNAVAILABLE, "Failed to init ADE7953");
}

if (c->calib.done && false) { //do not use for now
LOG(LL_INFO, ("gains: av %f ai %f aw %f", c->calib.gains0.avgain,
c->calib.gains0.aigain, c->calib.gains0.awgain));
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AVGAIN,
c->calib.gains0.avgain);
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AIGAIN,
c->calib.gains0.aigain);
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_AWGAIN,
c->calib.gains0.awgain);
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BVGAIN,
c->calib.gains0.bvgain);
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BIGAIN,
c->calib.gains0.bigain);
mgos_ade7953_write_reg(s_ade7953, MGOS_ADE7953_REG_BWGAIN,
c->calib.gains0.bwgain);
}

Status st;
std::unique_ptr<PowerMeter> pm1(new ADE7953PowerMeter(1, s_ade7953, 0));
if (!(st = pm1->Init()).ok()) return st;
Expand All @@ -83,9 +176,20 @@ void CreatePeripherals(std::vector<std::unique_ptr<Input>> *inputs,
std::vector<std::unique_ptr<Output>> *outputs,
std::vector<std::unique_ptr<PowerMeter>> *pms,
std::unique_ptr<TempSensor> *sys_temp) {
ReadFactoryData(&mgos_sys_config);

outputs->emplace_back(new OutputPin(1, 13, 1));
outputs->emplace_back(new OutputPin(2, 12, 1));
auto *in1 = new InputPin(1, 5, 1, MGOS_GPIO_PULL_NONE, true);

bool new_rev = false;
mgos_config_factory *c = &(mgos_sys_config.factory);
if (c->model != NULL && strcmp(c->model, "SNSW-102P16EU") == 0) {
new_rev = true;
}

int pin1 = new_rev ? 5 : 2;

auto *in1 = new InputPin(1, pin1, 1, MGOS_GPIO_PULL_NONE, true);
in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 4, _1, _2));
in1->Init();
inputs->emplace_back(in1);
Expand All @@ -99,26 +203,33 @@ void CreatePeripherals(std::vector<std::unique_ptr<Input>> *inputs,
LOG(LL_INFO, ("Failed to init ADE7953: %s", s.c_str()));
}

sys_temp->reset(new TempSensorSDNT1608X103F3950(35, 3.3f, 10000.0f));
int adc_pin = new_rev ? 35 : 37;
sys_temp->reset(new TempSensorSDNT1608X103F3950(adc_pin, 3.3f, 10000.0f));

int pin_out = 0;
int pin_in = 1;
// do not block uart when ESP_DBG_UART = 1
// this should be gpio19?

if (DetectAddon(pin_in, pin_out)) {
s_onewire.reset(new Onewire(pin_in, pin_out));
sensors = s_onewire->DiscoverAll();
if (sensors.empty()) {
s_onewire.reset();
sensors = DiscoverDHTSensors(pin_in, pin_out);
}
if (sensors.empty()) {
// No sensors detected, we assume to use addon as input for switch or
// closed/open sensor
auto *in2 = new InputPin(2, pin_in, 0, MGOS_GPIO_PULL_NONE, false);
in2->Init();
inputs->emplace_back(in2);
}
}
// int pin_out = 0;
// int pin_in = 1;

// if (DetectAddon(pin_in, pin_out)) {
// s_onewire.reset(new Onewire(pin_in, pin_out));
// sensors = s_onewire->DiscoverAll();
// if (sensors.empty()) {
// s_onewire.reset();
// sensors = DiscoverDHTSensors(pin_in, pin_out);
// }
// if (sensors.empty()) {
// // No sensors detected, we assume to use addon as input for switch or
// // closed/open sensor
// auto *in2 = new InputPin(2, pin_in, 0, MGOS_GPIO_PULL_NONE, false);
// in2->Init();
// inputs->emplace_back(in2);
// }
// }
//

// InitSysBtn(new_rev ? BTN_GPIO : 27, BTN_DOWN);
}

void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
Expand Down

0 comments on commit 6b9ad0f

Please sign in to comment.