From 6492dd0cddba146dee24f971241c81c69b72bde6 Mon Sep 17 00:00:00 2001 From: Timo Schilling Date: Wed, 1 Feb 2023 12:20:44 +0100 Subject: [PATCH] implement carbon dioxide and monoxide sensors (#1210) --- fs_src/index.html | 6 +++ fs_src/script.js | 22 ++++++++-- src/shelly_common.hpp | 4 ++ src/shelly_component.hpp | 2 + src/shelly_hap_carbon_dioxide_sensor.cpp | 49 +++++++++++++++++++++++ src/shelly_hap_carbon_dioxide_sensor.hpp | 36 +++++++++++++++++ src/shelly_hap_carbon_monoxide_sensor.cpp | 49 +++++++++++++++++++++++ src/shelly_hap_carbon_monoxide_sensor.hpp | 36 +++++++++++++++++ src/shelly_hap_input.cpp | 22 ++++++++++ 9 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 src/shelly_hap_carbon_dioxide_sensor.cpp create mode 100644 src/shelly_hap_carbon_dioxide_sensor.hpp create mode 100644 src/shelly_hap_carbon_monoxide_sensor.cpp create mode 100644 src/shelly_hap_carbon_monoxide_sensor.hpp diff --git a/fs_src/index.html b/fs_src/index.html index eece9c02..aaede933 100644 --- a/fs_src/index.html +++ b/fs_src/index.html @@ -550,6 +550,8 @@

Input

+ +
@@ -601,6 +603,8 @@

Disabled Input

+ +
@@ -630,6 +634,8 @@

Sensor

+ +
diff --git a/fs_src/script.js b/fs_src/script.js index ceae40fe..8c7a9623 100644 --- a/fs_src/script.js +++ b/fs_src/script.js @@ -60,7 +60,9 @@ class Component_Type { static kTemperatureSensor = 12; static kLeakSensor = 13; static kSmokeSensor = 14; - static kMax = 15; + static kCarbonMonoxideSensor = 15; + static kCarbonDioxideSensor = 16; + static kMax = 17; }; // Keep in sync with shelly::LightBulbController::BulbType. @@ -592,6 +594,8 @@ function findOrAddContainer(cd) { case Component_Type.kContactSensor: case Component_Type.kLeakSensor: case Component_Type.kSmokeSensor: + case Component_Type.kCarbonMonoxideSensor: + case Component_Type.kCarbonDioxideSensor: c = el("sensor_template").cloneNode(true); c.id = elId; el(c, "save_btn").onclick = function() { @@ -662,6 +666,7 @@ function rgbState(c, newState) { function updateComponent(cd) { let c = findOrAddContainer(cd); + let whatSensor; if (!c) return; switch (cd.type) { case Component_Type.kSwitch: @@ -864,10 +869,19 @@ function updateComponent(cd) { break; } case Component_Type.kMotionSensor: + whatSensor || = "motion"; case Component_Type.kOccupancySensor: + whatSensor || = "occupancy"; case Component_Type.kContactSensor: + whatSensor || = "contact"; case Component_Type.kLeakSensor: - case Component_Type.kSmokeSensor: { + whatSensor || = "leak"; + case Component_Type.kSmokeSensor: + whatSensor || = "smoke"; + case Component_Type.kCarbonMonoxideSensor: + whatSensor || = "carbon monoxide"; + case Component_Type.kCarbonDioxideSensor: { + whatSensor || = "carbon dioxide"; let headText = `Input ${cd.id}`; if (cd.name) headText += ` (${cd.name})`; updateInnerText(el(c, "head"), headText); @@ -878,8 +892,8 @@ function updateComponent(cd) { setValueIfNotModified(el(c, "idle_time"), cd.idle_time); el(c, "idle_time_container").style.display = (cd.in_mode == 0 ? "none" : "block"); - let what = (cd.type == 7 ? "motion" : "occupancy"); - let statusText = (cd.state ? `${what} detected` : `no ${what} detected`); + let statusText = + (cd.state ? `${whatSensor} detected` : `no ${whatSensor} detected`); if (cd.last_ev_age > 0) { statusText += `; last ${secondsToDateString(cd.last_ev_age)} ago`; } diff --git a/src/shelly_common.hpp b/src/shelly_common.hpp index 6019382b..78b69100 100644 --- a/src/shelly_common.hpp +++ b/src/shelly_common.hpp @@ -41,6 +41,8 @@ #define SHELLY_HAP_AID_BASE_TEMPERATURE_SENSOR 0xc00 #define SHELLY_HAP_AID_BASE_LEAK_SENSOR 0xe00 #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_IID_BASE_SWITCH 0x100 #define SHELLY_HAP_IID_STEP_SWITCH 4 @@ -67,6 +69,8 @@ #define SHELLY_HAP_IID_BASE_LEAK_SENSOR 0xe00 #define SHELLY_HAP_IID_BASE_SMOKE_SENSOR 0xf00 #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 kChangeReasonAuto "AUTO" #define kChangeReasonAutoWithNotification "AUTO_NOTIFICATION" diff --git a/src/shelly_component.hpp b/src/shelly_component.hpp index f69df0aa..5cea14fa 100644 --- a/src/shelly_component.hpp +++ b/src/shelly_component.hpp @@ -40,6 +40,8 @@ class Component { kTemperatureSensor = 12, kLeakSensor = 13, kSmokeSensor = 14, + kCarbonMonoxideSensor = 15, + kCarbonDioxideSensor = 16, kMax, }; diff --git a/src/shelly_hap_carbon_dioxide_sensor.cpp b/src/shelly_hap_carbon_dioxide_sensor.cpp new file mode 100644 index 00000000..2aab351e --- /dev/null +++ b/src/shelly_hap_carbon_dioxide_sensor.cpp @@ -0,0 +1,49 @@ +/* + * 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_carbon_dioxide_sensor.hpp" + +namespace shelly { +namespace hap { + +CarbonDioxideSensor::CarbonDioxideSensor(int id, Input *in, + struct mgos_config_in_sensor *cfg) + : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_CARBON_DIOXIDE_SENSOR, + &kHAPServiceType_CarbonDioxideSensor, + kHAPServiceDebugDescription_CarbonDioxideSensor) { +} + +CarbonDioxideSensor::~CarbonDioxideSensor() { +} + +Component::Type CarbonDioxideSensor::type() const { + return Type::kCarbonDioxideSensor; +} + +Status CarbonDioxideSensor::Init() { + const Status &st = SensorBase::Init(); + if (!st.ok()) return st; + AddChar(new mgos::hap::UInt8Characteristic( + svc_.iid + 2, &kHAPCharacteristicType_CarbonDioxideDetected, 0, 1, 1, + std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), + true /* supports_notification */, nullptr /* write_handler */, + kHAPCharacteristicDebugDescription_CarbonDioxideDetected)); + return Status::OK(); +} + +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_carbon_dioxide_sensor.hpp b/src/shelly_hap_carbon_dioxide_sensor.hpp new file mode 100644 index 00000000..59526745 --- /dev/null +++ b/src/shelly_hap_carbon_dioxide_sensor.hpp @@ -0,0 +1,36 @@ +/* + * 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 "shelly_hap_sensor_base.hpp" + +namespace shelly { +namespace hap { + +class CarbonDioxideSensor : public SensorBase { + public: + CarbonDioxideSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); + virtual ~CarbonDioxideSensor(); + + // Component interface impl. + Status Init() override; + virtual Type type() const override; +}; + +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_carbon_monoxide_sensor.cpp b/src/shelly_hap_carbon_monoxide_sensor.cpp new file mode 100644 index 00000000..b0600b56 --- /dev/null +++ b/src/shelly_hap_carbon_monoxide_sensor.cpp @@ -0,0 +1,49 @@ +/* + * 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_carbon_monoxide_sensor.hpp" + +namespace shelly { +namespace hap { + +CarbonMonoxideSensor::CarbonMonoxideSensor(int id, Input *in, + struct mgos_config_in_sensor *cfg) + : SensorBase(id, in, cfg, SHELLY_HAP_IID_BASE_CARBON_MONOXIDE_SENSOR, + &kHAPServiceType_CarbonMonoxideSensor, + kHAPServiceDebugDescription_CarbonMonoxideSensor) { +} + +CarbonMonoxideSensor::~CarbonMonoxideSensor() { +} + +Component::Type CarbonMonoxideSensor::type() const { + return Type::kCarbonMonoxideSensor; +} + +Status CarbonMonoxideSensor::Init() { + const Status &st = SensorBase::Init(); + if (!st.ok()) return st; + AddChar(new mgos::hap::UInt8Characteristic( + svc_.iid + 2, &kHAPCharacteristicType_CarbonMonoxideDetected, 0, 1, 1, + std::bind(&mgos::hap::ReadUInt8, _1, _2, _3, &state_), + true /* supports_notification */, nullptr /* write_handler */, + kHAPCharacteristicDebugDescription_CarbonMonoxideDetected)); + return Status::OK(); +} + +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_carbon_monoxide_sensor.hpp b/src/shelly_hap_carbon_monoxide_sensor.hpp new file mode 100644 index 00000000..3afe46b0 --- /dev/null +++ b/src/shelly_hap_carbon_monoxide_sensor.hpp @@ -0,0 +1,36 @@ +/* + * 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 "shelly_hap_sensor_base.hpp" + +namespace shelly { +namespace hap { + +class CarbonMonoxideSensor : public SensorBase { + public: + CarbonMonoxideSensor(int id, Input *in, struct mgos_config_in_sensor *cfg); + virtual ~CarbonMonoxideSensor(); + + // Component interface impl. + Status Init() override; + virtual Type type() const override; +}; + +} // namespace hap +} // namespace shelly diff --git a/src/shelly_hap_input.cpp b/src/shelly_hap_input.cpp index a5fedb78..d7db7d2c 100644 --- a/src/shelly_hap_input.cpp +++ b/src/shelly_hap_input.cpp @@ -20,6 +20,8 @@ #include "mgos.hpp" #include "mgos_hap.h" +#include "shelly_hap_carbon_dioxide_sensor.hpp" +#include "shelly_hap_carbon_monoxide_sensor.hpp" #include "shelly_hap_contact_sensor.hpp" #include "shelly_hap_doorbell.hpp" #include "shelly_hap_leak_sensor.hpp" @@ -156,6 +158,20 @@ Status ShellyInput::Init() { s_ = cs; break; } + case Type::kCarbonMonoxideSensor: { + auto *cs = new hap::CarbonMonoxideSensor( + id(), in_, (struct mgos_config_in_sensor *) &cfg_->sensor); + c_.reset(cs); + s_ = cs; + break; + } + case Type::kCarbonDioxideSensor: { + auto *cs = new hap::CarbonDioxideSensor( + id(), in_, (struct mgos_config_in_sensor *) &cfg_->sensor); + c_.reset(cs); + s_ = cs; + break; + } default: { return mgos::Errorf(STATUS_INVALID_ARGUMENT, "Invalid type %d", (int) initial_type_); @@ -225,6 +241,10 @@ uint16_t ShellyInput::GetAIDBase() const { return SHELLY_HAP_AID_BASE_LEAK_SENSOR; case Type::kSmokeSensor: return SHELLY_HAP_AID_BASE_SMOKE_SENSOR; + case Type::kCarbonMonoxideSensor: + return SHELLY_HAP_AID_BASE_CARBON_MONOXIDE_SENSOR; + case Type::kCarbonDioxideSensor: + return SHELLY_HAP_AID_BASE_CARBON_DIOXIDE_SENSOR; default: return 0; } @@ -245,6 +265,8 @@ bool ShellyInput::IsValidType(int type) { case (int) Type::kDoorbell: case (int) Type::kLeakSensor: case (int) Type::kSmokeSensor: + case (int) Type::kCarbonMonoxideSensor: + case (int) Type::kCarbonDioxideSensor: return true; } return false;