From f56f7d9fd8cca5fc08daa47a410f4016b49d40fe Mon Sep 17 00:00:00 2001 From: Markus Kirberg Date: Sun, 30 Oct 2022 12:42:32 +0100 Subject: [PATCH] format and split --- src/DHT/shelly_dht_sensor.cpp | 13 ++- src/DHT/shelly_dht_sensor.hpp | 4 +- src/Shelly1/shelly_init.cpp | 21 ++-- src/Shelly1PM/shelly_init.cpp | 24 ++++- src/shelly_common.hpp | 2 + src/shelly_hap_humidity_sensor.cpp | 149 ++++++++++++++++++++++++++ src/shelly_hap_humidity_sensor.hpp | 56 ++++++++++ src/shelly_hap_temperature_sensor.cpp | 2 +- src/shelly_hap_temperature_sensor.hpp | 5 +- src/shelly_main.cpp | 26 ++++- src/shelly_main.hpp | 9 +- src/shelly_temp_sensor.cpp | 4 + src/shelly_temp_sensor.hpp | 9 ++ 13 files changed, 297 insertions(+), 27 deletions(-) create mode 100644 src/shelly_hap_humidity_sensor.cpp create mode 100644 src/shelly_hap_humidity_sensor.hpp diff --git a/src/DHT/shelly_dht_sensor.cpp b/src/DHT/shelly_dht_sensor.cpp index afccd2f5..885babfe 100644 --- a/src/DHT/shelly_dht_sensor.cpp +++ b/src/DHT/shelly_dht_sensor.cpp @@ -21,8 +21,8 @@ namespace shelly { -DHTSensor::DHTSensor(uint8_t pin_in, uint8_t pin_out) : - pin_in_(pin_in), +DHTSensor::DHTSensor(uint8_t pin_in, uint8_t pin_out) + : pin_in_(pin_in), pin_out_(pin_out), meas_timer_(std::bind(&DHTSensor::UpdateTemperatureCB, this)) { result_ = mgos::Errorf(STATUS_UNAVAILABLE, "Not updated yet"); @@ -42,8 +42,8 @@ Status DHTSensor::Init() { result_ = mgos_dht_get_temp(dht); mgos_dht_stats stats; - if(mgos_dht_getStats(dht, &stats)) { - if(stats.read == 1 && stats.read_success == 1) { + if (mgos_dht_getStats(dht, &stats)) { + if (stats.read == 1 && stats.read_success == 1) { return Status::OK(); } } @@ -63,12 +63,15 @@ StatusOr DHTSensor::GetHumidity() { } void DHTSensor::UpdateTemperatureCB() { - //std::nan + // std::nan result_ = mgos_dht_get_temp(dht); result_humidity_ = mgos_dht_get_humidity(dht); if (notifier_) { notifier_(); } + if (notifier_hum_) { + notifier_hum_(); + } } } // namespace shelly diff --git a/src/DHT/shelly_dht_sensor.hpp b/src/DHT/shelly_dht_sensor.hpp index 28ea777d..12edaad9 100644 --- a/src/DHT/shelly_dht_sensor.hpp +++ b/src/DHT/shelly_dht_sensor.hpp @@ -25,14 +25,14 @@ namespace shelly { -class DHTSensor : public TempSensor { +class DHTSensor : public HumidityTempSensor { public: DHTSensor(uint8_t pin_in, uint8_t pin_out); virtual ~DHTSensor(); Status Init(); StatusOr GetTemperature() override; - StatusOr GetHumidity(); + StatusOr GetHumidity() override; virtual void StartUpdating(int interval) override; diff --git a/src/Shelly1/shelly_init.cpp b/src/Shelly1/shelly_init.cpp index 4b8f832d..c8dfb667 100644 --- a/src/Shelly1/shelly_init.cpp +++ b/src/Shelly1/shelly_init.cpp @@ -17,12 +17,12 @@ #include "mgos_hap.h" +#include "shelly_dht_sensor.hpp" #include "shelly_hap_garage_door_opener.hpp" #include "shelly_hap_temperature_sensor.hpp" #include "shelly_input_pin.hpp" #include "shelly_main.hpp" #include "shelly_temp_sensor_ow.hpp" -#include "shelly_dht_sensor.hpp" #define MAX_TS_NUM 3 @@ -72,17 +72,17 @@ void CreateComponents(std::vector> *comps, // Sensor Discovery std::unique_ptr dht; + bool dht_found = false; sensors.clear(); if (s_onewire != nullptr) { sensors = s_onewire->DiscoverAll(); - } - else { - //Try DHT, only works on second boot + } else { + // Try DHT, only works on second boot dht.reset(new DHTSensor(3, 0)); auto status = dht->Init(); - if(status == Status::OK()) { - + if (status == Status::OK()) { sensors.push_back(std::move(dht)); + dht_found = true; } } @@ -101,8 +101,13 @@ void CreateComponents(std::vector> *comps, for (size_t i = 0; i < std::min((size_t) MAX_TS_NUM, sensors.size()); i++) { auto *ts_cfg = ts_cfgs[i]; - CreateHAPTemperatureSensor(i + 1, sensors[i].get(), ts_cfg, comps, - accs, svr); + CreateHAPTemperatureSensor(i + 1, sensors[i].get(), ts_cfg, comps, accs, + svr); + HumidityTempSensor *hum = (HumidityTempSensor *) sensors[i].get(); + if (dht_found) { // can only be one shares config, as same update + // interval but no unit settable + CreateHAPHumiditySensor(i + 2, hum, ts_cfg, comps, accs, svr); + } } } } diff --git a/src/Shelly1PM/shelly_init.cpp b/src/Shelly1PM/shelly_init.cpp index 898abe12..b7cc535b 100644 --- a/src/Shelly1PM/shelly_init.cpp +++ b/src/Shelly1PM/shelly_init.cpp @@ -15,6 +15,7 @@ * limitations under the License. */ +#include "shelly_dht_sensor.hpp" #include "shelly_hap_garage_door_opener.hpp" #include "shelly_input_pin.hpp" #include "shelly_main.hpp" @@ -28,6 +29,7 @@ namespace shelly { static std::unique_ptr s_onewire; +static std::vector> sensors; void CreatePeripherals(std::vector> *inputs, std::vector> *outputs, @@ -84,11 +86,20 @@ void CreateComponents(std::vector> *comps, } // Sensor Discovery - std::vector> sensors; + std::unique_ptr dht; + bool dht_found = false; + sensors.clear(); if (s_onewire != nullptr) { sensors = s_onewire->DiscoverAll(); + } else { + // Try DHT, only works on second boot + dht.reset(new DHTSensor(3, 0)); + auto status = dht->Init(); + if (status == Status::OK()) { + sensors.push_back(std::move(dht)); + dht_found = true; + } } - // 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)); @@ -104,8 +115,13 @@ void CreateComponents(std::vector> *comps, for (size_t i = 0; i < std::min((size_t) MAX_TS_NUM, sensors.size()); i++) { auto *ts_cfg = ts_cfgs[i]; - CreateHAPTemperatureSensor(i + 1, std::move(sensors[i]), ts_cfg, comps, - accs, svr); + CreateHAPTemperatureSensor(i + 1, sensors[i].get(), ts_cfg, comps, accs, + svr); + HumidityTempSensor *hum = (HumidityTempSensor *) sensors[i].get(); + if (dht_found) { // can only be one shares config, as same update + // interval but no unit settable + CreateHAPHumiditySensor(i + 2, hum, ts_cfg, comps, accs, svr); + } } } } diff --git a/src/shelly_common.hpp b/src/shelly_common.hpp index 78b69100..70fbc3a9 100644 --- a/src/shelly_common.hpp +++ b/src/shelly_common.hpp @@ -43,6 +43,7 @@ #define SHELLY_HAP_AID_BASE_SMOKE_SENSOR 0xf00 #define SHELLY_HAP_AID_BASE_CARBON_MONOXIDE_SENSOR 0x1000 #define SHELLY_HAP_AID_BASE_CARBON_DIOXIDE_SENSOR 0x1100 +#define SHELLY_HAP_AID_BASE_HUMIDITY_SENSOR 0x1200 #define SHELLY_HAP_IID_BASE_SWITCH 0x100 #define SHELLY_HAP_IID_STEP_SWITCH 4 @@ -71,6 +72,7 @@ #define SHELLY_HAP_IID_BASE_ADAPTIVE_LIGHTING 0x1000 #define SHELLY_HAP_IID_BASE_CARBON_MONOXIDE_SENSOR 0x1100 #define SHELLY_HAP_IID_BASE_CARBON_DIOXIDE_SENSOR 0x1200 +#define SHELLY_HAP_IID_BASE_HUMIDITY_SENSOR 0x1300 #define kChangeReasonAuto "AUTO" #define kChangeReasonAutoWithNotification "AUTO_NOTIFICATION" diff --git a/src/shelly_hap_humidity_sensor.cpp b/src/shelly_hap_humidity_sensor.cpp new file mode 100644 index 00000000..7043d21b --- /dev/null +++ b/src/shelly_hap_humidity_sensor.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) Shelly-HomeKit Contributors + * All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "shelly_hap_humidity_sensor.hpp" + +#include + +#include "mgos.hpp" + +namespace shelly { +namespace hap { + +HumiditySensor::HumiditySensor(int id, HumidityTempSensor *sensor, + struct mgos_config_ts *cfg) + : Component(id), + Service(SHELLY_HAP_IID_BASE_HUMIDITY_SENSOR + + SHELLY_HAP_IID_STEP_SENSOR * (id - 1), + &kHAPServiceType_HumiditySensor, + kHAPServiceDebugDescription_HumiditySensor), + hum_sensor_(sensor), + cfg_(cfg) { + hum_sensor_->SetNotifierHumidity( + std::bind(&HumiditySensor::ValueChanged, this)); +} + +HumiditySensor::~HumiditySensor() { + hum_sensor_->SetNotifier(nullptr); +} + +Component::Type HumiditySensor::type() const { + return Type::kTemperatureSensor; +} + +std::string HumiditySensor::name() const { + return cfg_->name; +} + +Status HumiditySensor::SetConfig(const std::string &config_json, + bool *restart_required) { + struct mgos_config_ts cfg = *cfg_; + cfg.name = nullptr; + json_scanf(config_json.c_str(), config_json.size(), + "{name: %Q, unit: %d, update_interval: %d", &cfg.name, &cfg.unit, + &cfg.update_interval); + + mgos::ScopedCPtr name_owner((void *) cfg.name); + // Validation. + if (cfg.name != nullptr && strlen(cfg.name) > 64) { + return mgos::Errorf(STATUS_INVALID_ARGUMENT, "invalid %s", + "name (too long, max 64)"); + } + if (cfg.unit < 0 || cfg.unit > 1) { + return mgos::Errorf(STATUS_INVALID_ARGUMENT, "invalid unit"); + } + if (cfg.update_interval < 1) { + return mgos::Errorf(STATUS_INVALID_ARGUMENT, "invalid update interval"); + } + // Now copy over. + if (cfg_->name != nullptr && strcmp(cfg_->name, cfg.name) != 0) { + mgos_conf_set_str(&cfg_->name, cfg.name); + *restart_required = true; + } + if (cfg_->unit != cfg.unit) { + cfg_->unit = cfg.unit; + } + if (cfg_->update_interval != cfg.update_interval) { + cfg_->update_interval = cfg.update_interval; + hum_sensor_->StartUpdating(cfg_->update_interval * 1000); + } + return Status::OK(); +} + +Status HumiditySensor::SetState(const std::string &state_json UNUSED_ARG) { + return Status::OK(); +} + +void HumiditySensor::ValueChanged() { + auto tr = hum_sensor_->GetTemperature(); + if (tr.ok()) { + LOG(LL_DEBUG, ("TS %d: T = %.2f", id(), tr.ValueOrDie())); + } else { + LOG(LL_ERROR, ("TS %d: %s", id(), tr.status().ToString().c_str())); + } + current_humidity_characteristic_->RaiseEvent(); +} + +Status HumiditySensor::Init() { + uint16_t iid = svc_.iid + 1; + current_humidity_characteristic_ = new mgos::hap::FloatCharacteristic( + iid++, &kHAPCharacteristicType_CurrentRelativeHumidity, 0, 100.0, 1, + [this](HAPAccessoryServerRef *server UNUSED_ARG, + const HAPFloatCharacteristicReadRequest *request UNUSED_ARG, + float *value) { + auto tempval = hum_sensor_->GetHumidity(); + if (!tempval.ok()) { + return kHAPError_Busy; + } + float temp = static_cast(tempval.ValueOrDie()); + *value = truncf(temp * 10) / 10; + return kHAPError_None; + }, + + true /* supports_notification */, nullptr /* write_handler */, + kHAPCharacteristicDebugDescription_CurrentRelativeHumidity); + AddChar(current_humidity_characteristic_); + + hum_sensor_->StartUpdating(cfg_->update_interval * 1000); + return Status::OK(); +} + +StatusOr HumiditySensor::GetInfo() const { + auto tempval = hum_sensor_->GetHumidity(); + if (!tempval.ok()) { + return tempval.status(); + } + return mgos::SPrintf("t:%.2f", tempval.ValueOrDie()); +} + +StatusOr HumiditySensor::GetInfoJSON() const { + std::string res = mgos::JSONPrintStringf( + "{id: %d, type: %d, name: %Q, unit: %d, " + "update_interval: %d, ", + id(), type(), cfg_->name, cfg_->unit, cfg_->update_interval); + auto tempval = hum_sensor_->GetHumidity(); + if (tempval.ok()) { + mgos::JSONAppendStringf(&res, "value: %.1f", tempval.ValueOrDie()); + } else { + mgos::JSONAppendStringf(&res, "error: %.1f", tempval.ValueOrDie()); + } + res.append("}"); + return res; +} + +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_humidity_sensor.hpp b/src/shelly_hap_humidity_sensor.hpp new file mode 100644 index 00000000..0b532e90 --- /dev/null +++ b/src/shelly_hap_humidity_sensor.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) Shelly-HomeKit Contributors + * All rights reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "mgos_hap_service.hpp" +#include "mgos_sys_config.h" + +#include "shelly_common.hpp" +#include "shelly_component.hpp" +#include "shelly_temp_sensor.hpp" + +namespace shelly { +namespace hap { + +class HumiditySensor : public Component, public mgos::hap::Service { + public: + HumiditySensor(int id, HumidityTempSensor *sensor, + struct mgos_config_ts *cfg); + virtual ~HumiditySensor(); + + // Component interface impl. + Type type() const override; + std::string name() const override; + Status Init() override; + + StatusOr GetInfo() const override; + StatusOr GetInfoJSON() const override; + Status SetConfig(const std::string &config_json, + bool *restart_required) override; + Status SetState(const std::string &state_json) override; + + private: + HumidityTempSensor *hum_sensor_; + struct mgos_config_ts *cfg_; + + mgos::hap::FloatCharacteristic *current_humidity_characteristic_; + + void ValueChanged(); +}; +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_temperature_sensor.cpp b/src/shelly_hap_temperature_sensor.cpp index f2338ffc..d83d3f64 100644 --- a/src/shelly_hap_temperature_sensor.cpp +++ b/src/shelly_hap_temperature_sensor.cpp @@ -24,7 +24,7 @@ namespace shelly { namespace hap { -TemperatureSensor::TemperatureSensor(int id, TempSensor* sensor, +TemperatureSensor::TemperatureSensor(int id, TempSensor *sensor, struct mgos_config_ts *cfg) : Component(id), Service(SHELLY_HAP_IID_BASE_TEMPERATURE_SENSOR + diff --git a/src/shelly_hap_temperature_sensor.hpp b/src/shelly_hap_temperature_sensor.hpp index 2ea0d3e7..5e0467d3 100644 --- a/src/shelly_hap_temperature_sensor.hpp +++ b/src/shelly_hap_temperature_sensor.hpp @@ -30,8 +30,7 @@ namespace hap { class TemperatureSensor : public Component, public mgos::hap::Service { public: - TemperatureSensor(int id, TempSensor* sensor, - struct mgos_config_ts *cfg); + TemperatureSensor(int id, TempSensor *sensor, struct mgos_config_ts *cfg); virtual ~TemperatureSensor(); // Component interface impl. @@ -46,7 +45,7 @@ class TemperatureSensor : public Component, public mgos::hap::Service { Status SetState(const std::string &state_json) override; private: - TempSensor* temp_sensor_; + TempSensor *temp_sensor_; struct mgos_config_ts *cfg_; mgos::hap::FloatCharacteristic *current_temperature_characteristic_; diff --git a/src/shelly_main.cpp b/src/shelly_main.cpp index 6819051d..d49412ca 100644 --- a/src/shelly_main.cpp +++ b/src/shelly_main.cpp @@ -44,6 +44,7 @@ #include "HAPPlatformTCPStreamManager+Init.h" #include "shelly_debug.hpp" +#include "shelly_hap_humidity_sensor.hpp" #include "shelly_hap_input.hpp" #include "shelly_hap_lock.hpp" #include "shelly_hap_outlet.hpp" @@ -215,8 +216,7 @@ void CreateHAPSwitch(int id, const struct mgos_config_sw *sw_cfg, } void CreateHAPTemperatureSensor( - int id, TempSensor * sensor, - const struct mgos_config_ts *ts_cfg, + int id, TempSensor *sensor, const struct mgos_config_ts *ts_cfg, std::vector> *comps, std::vector> *accs, HAPAccessoryServerRef *svr) { @@ -237,6 +237,28 @@ void CreateHAPTemperatureSensor( comps->push_back(std::move(ts)); } +void CreateHAPHumiditySensor( + int id, HumidityTempSensor *sensor, const struct mgos_config_ts *ts_cfg, + std::vector> *comps, + std::vector> *accs, + HAPAccessoryServerRef *svr) { + struct mgos_config_ts *cfg = (struct mgos_config_ts *) ts_cfg; + std::unique_ptr ts( + new hap::HumiditySensor(id, sensor, cfg)); + if (ts == nullptr || !ts->Init().ok()) { + return; + } + + std::unique_ptr acc( + new mgos::hap::Accessory(SHELLY_HAP_AID_BASE_HUMIDITY_SENSOR + id, + kHAPAccessoryCategory_BridgedAccessory, + ts_cfg->name, GetIdentifyCB(), svr)); + acc->AddHAPService(&mgos_hap_accessory_information_service); + acc->AddService(ts.get()); + accs->push_back(std::move(acc)); + comps->push_back(std::move(ts)); +} + static void DisableLegacyHAPLayout() { if (!mgos_sys_config_get_shelly_legacy_hap_layout()) return; LOG(LL_INFO, ("Turning off legacy HAP layout")); diff --git a/src/shelly_main.hpp b/src/shelly_main.hpp index d953ba87..a855b5a9 100644 --- a/src/shelly_main.hpp +++ b/src/shelly_main.hpp @@ -52,8 +52,13 @@ void CreateHAPSwitch(int id, const struct mgos_config_sw *sw_cfg, Output *led_out = nullptr); void CreateHAPTemperatureSensor( - int id, TempSensor* sensor, - const struct mgos_config_ts *ts_cfg, + int id, TempSensor *sensor, const struct mgos_config_ts *ts_cfg, + std::vector> *comps, + std::vector> *accs, + HAPAccessoryServerRef *svr); + +void CreateHAPHumiditySensor( + int id, HumidityTempSensor *sensor, const struct mgos_config_ts *ts_cfg, std::vector> *comps, std::vector> *accs, HAPAccessoryServerRef *svr); diff --git a/src/shelly_temp_sensor.cpp b/src/shelly_temp_sensor.cpp index b9a390fd..6cf4e5b6 100644 --- a/src/shelly_temp_sensor.cpp +++ b/src/shelly_temp_sensor.cpp @@ -29,4 +29,8 @@ void TempSensor::SetNotifier(Notifier notifier) { notifier_ = notifier; } +void HumidityTempSensor::SetNotifierHumidity(Notifier notifier) { + notifier_hum_ = notifier; +} + } // namespace shelly diff --git a/src/shelly_temp_sensor.hpp b/src/shelly_temp_sensor.hpp index 64ad65b8..92b07605 100644 --- a/src/shelly_temp_sensor.hpp +++ b/src/shelly_temp_sensor.hpp @@ -42,4 +42,13 @@ class TempSensor { Notifier notifier_; }; +class HumidityTempSensor : public TempSensor { + public: + virtual StatusOr GetHumidity() = 0; + void SetNotifierHumidity(Notifier notifier); + + protected: + Notifier notifier_hum_; +}; + } // namespace shelly