Skip to content

Commit

Permalink
Shelly1/PM: Support Addon as Switch (Input) with autodetect
Browse files Browse the repository at this point in the history
wip

more elaborate addon detection
  • Loading branch information
markirb committed Nov 24, 2023
1 parent ceb8cb3 commit 366c8d2
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 35 deletions.
15 changes: 12 additions & 3 deletions mos.yml
Expand Up @@ -231,9 +231,12 @@ conds:
- ["in1", "in", {title: "Input 1 settings"}]
- ["in1.ssw.name", "Shelly SSW1"]
- ["in1.sensor.name", "Shelly S1"]
- ["in2", "in", {title: "Input 2 settings"}]
- ["in2.ssw.name", "Shelly SSW2"]
- ["in2.sensor.name", "Shelly S2"]
- ["gdo1", "gdo", {title: "GDO1 settings"}]
- ["gdo1.name", "Garage Door"]
- ["gdo1.open_sensor_mode", -1]
- ["gdo1.open_sensor_mode", 2]
# Only for backward compatibility (config <= v3).
- ["ssw1", "ssw", {title: "SSW1 settings"}]
- ["ssw1.name", "Input"]
Expand Down Expand Up @@ -315,9 +318,12 @@ conds:
- ["in1", "in", {title: "Input 1 settings"}]
- ["in1.ssw.name", "Shelly SSW1"]
- ["in1.sensor.name", "Shelly S1"]
- ["in2", "in", {title: "Input 2 settings"}]
- ["in2.ssw.name", "Shelly SSW2"]
- ["in2.sensor.name", "Shelly S2"]
- ["gdo1", "gdo", {title: "GDO1 settings"}]
- ["gdo1.name", "Garage Door"]
- ["gdo1.open_sensor_mode", -1]
- ["gdo1.open_sensor_mode", 2]
- ["bl0937.power_coeff", "f", 0, {title: "BL0937 counts -> watts conversion coefficient"}]
- ["bl0937.power_coeff", 1.79942025] # (16 + 1010 + 1935) / (8.53 + 561 + 1076)
# Only for backward compatibility (config <= v3).
Expand Down Expand Up @@ -592,7 +598,7 @@ conds:
- ["in1.sensor.name", "Shelly S1"]
- ["gdo1", "gdo", {title: "GDO1 settings"}]
- ["gdo1.name", "Garage Door"]
- ["gdo1.open_sensor_mode", -1]
- ["gdo1.open_sensor_mode", 2]
# Only for backward compatibility (config <= v3).
- ["ssw1", "ssw", {title: "SSW1 settings"}]
- ["ssw1.name", "Input"]
Expand Down Expand Up @@ -839,6 +845,9 @@ conds:
- ["in1", "in", {title: "Input 1 settings"}]
- ["in1.ssw.name", "ShellyU SSW1"]
- ["in1.sensor.name", "ShellyU S1"]
- ["in2", "in", {title: "Input 2 settings"}]
- ["in2.ssw.name", "ShellyU SSW2"]
- ["in2.sensor.name", "ShellyU S2"]

- when: build_vars.MODEL == "ShellyUDuo"
apply:
Expand Down
42 changes: 28 additions & 14 deletions src/Shelly1/shelly_init.cpp
Expand Up @@ -18,6 +18,7 @@
#include "mgos_hap.h"

#include "shelly_hap_garage_door_opener.hpp"
#include "shelly_hap_input.hpp"
#include "shelly_hap_temperature_sensor.hpp"
#include "shelly_input_pin.hpp"
#include "shelly_main.hpp"
Expand All @@ -34,26 +35,34 @@ void CreatePeripherals(std::vector<std::unique_ptr<Input>> *inputs,
std::vector<std::unique_ptr<PowerMeter>> *pms UNUSED_ARG,
std::unique_ptr<TempSensor> *sys_temp UNUSED_ARG) {
outputs->emplace_back(new OutputPin(1, 4, 1));
auto *in = new InputPin(1, 5, 1, MGOS_GPIO_PULL_NONE, true);
in->AddHandler(std::bind(&HandleInputResetSequence, in, 4, _1, _2));
in->Init();
inputs->emplace_back(in);

s_onewire.reset(new Onewire(3, 0));
if (s_onewire->DiscoverAll().empty()) {
s_onewire.reset();
auto *in1 = new InputPin(1, 5, 1, MGOS_GPIO_PULL_NONE, true);
in1->AddHandler(std::bind(&HandleInputResetSequence, in1, 4, _1, _2));
in1->Init();
inputs->emplace_back(in1);

bool addon_detected = DetectAddon(3, 0);

if (addon_detected) {
s_onewire.reset(new Onewire(3, 0));
if (s_onewire->DiscoverAll().empty()) {
s_onewire.reset();

// No sensor detected, we assume we have a switch attached
auto *in2 = new InputPin(2, 3, 0, MGOS_GPIO_PULL_NONE, false);
in2->Init();
inputs->emplace_back(in2);
}
}
}

void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
std::vector<std::unique_ptr<mgos::hap::Accessory>> *accs,
HAPAccessoryServerRef *svr) {
// Garage door opener mode.
if (mgos_sys_config_get_shelly_mode() == 2) {
if (mgos_sys_config_get_shelly_mode() == (int) Mode::kGarageDoor) {
auto *gdo_cfg = (struct mgos_config_gdo *) mgos_sys_config_get_gdo1();
std::unique_ptr<hap::GarageDoorOpener> gdo(
new hap::GarageDoorOpener(1, FindInput(1), nullptr /* in_open */,
FindOutput(1), FindOutput(1), gdo_cfg));

std::unique_ptr<hap::GarageDoorOpener> gdo(new hap::GarageDoorOpener(
1, FindInput(1), FindInput(2), FindOutput(1), FindOutput(1), gdo_cfg));
if (gdo == nullptr) return;
auto st = gdo->Init();
if (!st.ok()) {
Expand All @@ -74,9 +83,12 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
sensors = s_onewire->DiscoverAll();
}

bool ext_sensor_switch = (FindInput(2) != nullptr);

// Single switch with non-detached input and no sensors = only one accessory.
bool to_pri_acc = (sensors.empty() && (mgos_sys_config_get_sw1_in_mode() !=
(int) InMode::kDetached));
(int) InMode::kDetached)) &&
!ext_sensor_switch;
CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(),
comps, accs, svr, to_pri_acc);

Expand All @@ -92,6 +104,8 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
CreateHAPTemperatureSensor(i + 1, std::move(sensors[i]), ts_cfg, comps,
accs, svr);
}
} else if (ext_sensor_switch) {
hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr);
}
}

Expand Down
28 changes: 21 additions & 7 deletions src/Shelly1PM/shelly_init.cpp
Expand Up @@ -16,6 +16,7 @@
*/

#include "shelly_hap_garage_door_opener.hpp"
#include "shelly_hap_input.hpp"
#include "shelly_input_pin.hpp"
#include "shelly_main.hpp"
#include "shelly_pm_bl0937.hpp"
Expand Down Expand Up @@ -51,10 +52,19 @@ void CreatePeripherals(std::vector<std::unique_ptr<Input>> *inputs,
}
sys_temp->reset(new TempSensorSDNT1608X103F3950(0, 3.3f, 33000.0f));

s_onewire.reset(new Onewire(3, 0));
if (s_onewire->DiscoverAll().empty()) {
bool addon_detected = DetectAddon(3, 0);

if (addon_detected) {
s_onewire.reset(new Onewire(3, 0));
if (s_onewire->DiscoverAll().empty()) {
s_onewire.reset();

auto *in2 = new InputPin(2, 3, 0, MGOS_GPIO_PULL_NONE, false);
in2->Init();
inputs->emplace_back(in2);
}
} else {
// Sys LED shares the same pin.
s_onewire.reset();
InitSysLED(LED_GPIO, LED_ON);
}
InitSysBtn(BTN_GPIO, BTN_DOWN);
Expand All @@ -66,9 +76,8 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
if (mgos_sys_config_get_shelly_mode() == 2) {
// Garage door opener mode.
auto *gdo_cfg = (struct mgos_config_gdo *) mgos_sys_config_get_gdo1();
std::unique_ptr<hap::GarageDoorOpener> gdo(
new hap::GarageDoorOpener(1, FindInput(1), nullptr /* in_open */,
FindOutput(1), FindOutput(1), gdo_cfg));
std::unique_ptr<hap::GarageDoorOpener> gdo(new hap::GarageDoorOpener(
1, FindInput(1), FindInput(2), FindOutput(1), FindOutput(1), gdo_cfg));
if (gdo == nullptr) return;
auto st = gdo->Init();
if (!st.ok()) {
Expand All @@ -89,9 +98,12 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
sensors = s_onewire->DiscoverAll();
}

bool ext_sensor_switch = (FindInput(2) != nullptr);

// Single switch with non-detached input and no sensors = only one accessory.
bool to_pri_acc = (sensors.empty() && (mgos_sys_config_get_sw1_in_mode() !=
(int) InMode::kDetached));
(int) InMode::kDetached)) &&
!ext_sensor_switch;
CreateHAPSwitch(1, mgos_sys_config_get_sw1(), mgos_sys_config_get_in1(),
comps, accs, svr, to_pri_acc);

Expand All @@ -107,6 +119,8 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
CreateHAPTemperatureSensor(i + 1, std::move(sensors[i]), ts_cfg, comps,
accs, svr);
}
} else if (ext_sensor_switch) {
hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr);
}
}

Expand Down
32 changes: 21 additions & 11 deletions src/ShellyU/shelly_init.cpp
Expand Up @@ -21,6 +21,7 @@
#include "mgos_rpc.h"
#include "mgos_sys_config.h"

#include "shelly_hap_input.hpp"
#include "shelly_hap_temperature_sensor.hpp"
#include "shelly_input_pin.hpp"
#include "shelly_main.hpp"
Expand All @@ -33,9 +34,13 @@ 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) {
Input *in = new InputPin(1, 12, 1, MGOS_GPIO_PULL_NONE, true);
in->Init();
inputs->emplace_back(in);
auto *in1 = new InputPin(1, 12, 1, MGOS_GPIO_PULL_NONE, true);
in1->Init();
inputs->emplace_back(in1);

auto *in2 = new InputPin(2, 3, 0, MGOS_GPIO_PULL_NONE, false);
in2->Init();
inputs->emplace_back(in2);

outputs->emplace_back(new OutputPin(1, 34, 1));

Expand All @@ -53,15 +58,20 @@ void CreateComponents(std::vector<std::unique_ptr<Component>> *comps,
comps, accs, svr, false /* to_pri_acc */,
nullptr /* led_out */);

// Sensors
for (int i = 0; i < 2; i++) {
std::unique_ptr<TempSensor> temp(new MockTempSensor(25.125 + i));
auto *ts_cfg = (i == 0)
? (struct mgos_config_ts *) mgos_sys_config_get_ts1()
: (struct mgos_config_ts *) mgos_sys_config_get_ts2();
bool ext_switch_detected = false; // can be set for testing purposes

if (ext_switch_detected) {
hap::CreateHAPInput(2, mgos_sys_config_get_in2(), comps, accs, svr);
} else {
for (int i = 0; i < 2; i++) {
std::unique_ptr<TempSensor> temp(new MockTempSensor(25.125 + i));
auto *ts_cfg = (i == 0)
? (struct mgos_config_ts *) mgos_sys_config_get_ts1()
: (struct mgos_config_ts *) mgos_sys_config_get_ts2();

CreateHAPTemperatureSensor(i + 1, std::move(temp), ts_cfg, comps, accs,
svr);
CreateHAPTemperatureSensor(i + 1, std::move(temp), ts_cfg, comps, accs,
svr);
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/shelly_main.cpp
Expand Up @@ -119,6 +119,21 @@ static std::vector<const HAPAccessory *> s_hap_accs;
static std::unique_ptr<TempSensor> s_sys_temp_sensor;
std::vector<std::unique_ptr<Component>> g_comps;

bool DetectAddon(int pin_in, int pin_out) {
// case 1: input with pull up
mgos_gpio_setup_input(pin_in, MGOS_GPIO_PULL_UP);
// check if pulled by something external, not check output to input yet
bool active = mgos_gpio_read(pin_in);
if (!active) {
// something is pulling us low, we might have an addon with switchss
return true;
}

// Try to pull low via addon
mgos_gpio_setup_output(pin_out, 0 /* LOW */);
mgos_gpio_setup_input(pin_in, MGOS_GPIO_PULL_NONE);
return !mgos_gpio_read(pin_in);
}
template <class T>
T *FindById(const std::vector<std::unique_ptr<T>> &vv, int id) {
for (auto &v : vv) {
Expand Down
1 change: 1 addition & 0 deletions src/shelly_main.hpp
Expand Up @@ -40,6 +40,7 @@ namespace shelly {

extern std::vector<std::unique_ptr<Component>> g_comps;

bool DetectAddon(int pin_in, int pin_out);
Input *FindInput(int id);
Output *FindOutput(int id);
PowerMeter *FindPM(int id);
Expand Down

0 comments on commit 366c8d2

Please sign in to comment.