From eb1bc08591f70f74a3bd0d66c488a2278889e203 Mon Sep 17 00:00:00 2001 From: Goral64 Date: Sun, 7 Nov 2021 20:29:04 +0100 Subject: [PATCH 1/8] poprawki w HTML-u, dodanie dodatkowych iframe --- src/SuplaCommonPROGMEM.h | 91 ++++++++++++++++++++++++++-------------- src/SuplaWebServer.cpp | 5 ++- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/SuplaCommonPROGMEM.h b/src/SuplaCommonPROGMEM.h index c9e6efdf..4f0a2aba 100644 --- a/src/SuplaCommonPROGMEM.h +++ b/src/SuplaCommonPROGMEM.h @@ -23,36 +23,63 @@ #define PGMT(pgm_ptr) (reinterpret_cast(pgm_ptr)) const char HTTP_META[] PROGMEM = - "\n"; + "" + "\n"; const char HTTP_STYLE[] PROGMEM = - ""; - + ""; +const char HTTP_SCRIPT[] PROGMEM = + "\n"; +const char HTTP_DIV_START[] PROGMEM = + "
"; +const char HTTP_DIV_END[] PROGMEM = + "
"; const char HTTP_LOGO[] PROGMEM = - "
https://forum.supla.org/\n"; +const char HTTP_IFRAMES[] PROGMEM = + "
" + "
" + "
" + "
"; const char HTTP_FAVICON[] PROGMEM = "sendContent_P(HTTP_META); httpServer->sendContent_P(HTTP_FAVICON); httpServer->sendContent_P(HTTP_STYLE); + httpServer->sendContent_P(HTTP_SCRIPT); + httpServer->sendContent_P(HTTP_DIV_START); + httpServer->sendContent_P(HTTP_IFRAMES); httpServer->sendContent_P(HTTP_LOGO); String summary = FPSTR(HTTP_SUMMARY); @@ -98,7 +101,6 @@ void SuplaWebServer::sendHeaderStart() { summary.replace(F("{f}"), String(ESP.getFreeHeap() / 1024.0)); httpServer->sendContent(summary); - httpServer->sendContent_P(HTTP_COPYRIGHT); } } @@ -117,6 +119,7 @@ void SuplaWebServer::sendHeaderEnd() { if (chunkedSendHeader) { sendHeader(); httpServer->sendContent_P(HTTP_RBT); + httpServer->sendContent_P(HTTP_DIV_END); httpServer->chunkedResponseFinalize(); #ifdef ARDUINO_ARCH_ESP8266 From dc57a5bc373098ccbbc3bb739922a8066ae3f1bc Mon Sep 17 00:00:00 2001 From: Goral64 Date: Mon, 8 Nov 2021 16:29:47 +0100 Subject: [PATCH 2/8] =?UTF-8?q?wyr=C3=B3wnanie=20formatowania?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../action_trigger_tests.cpp | 638 +- lib/SuplaDevice/extras/test/CMakeLists.txt | 130 +- .../channel_element_tests.cpp | 174 +- .../test/ChannelTests/channel_tests.cpp | 1024 +-- .../test/ConditionTests/em_getter_tests.cpp | 844 +-- .../test/ConditionTests/on_less_tests.cpp | 784 +-- .../test/ElementTests/element_tests.cpp | 414 +- .../LocalActionTests/local_action_tests.cpp | 366 +- .../supla_device_full_startup_tests.cpp | 446 +- .../SuplaDeviceTests/supla_device_tests.cpp | 1314 ++-- .../extras/test/doubles/element_mock.h | 78 +- .../extras/test/doubles/srpc_mock.cpp | 290 +- .../extras/test/doubles/srpc_mock.h | 170 +- .../src/supla/sensor/MAXThermocouple.cpp | 180 +- .../src/supla/sensor/MAXThermocouple.h | 86 +- .../src/supla/sensor/hygro_meter.cpp | 36 +- .../src/supla/sensor/hygro_meter.h | 44 +- lib/SuplaDevice/src/CMakeLists.txt | 102 +- lib/SuplaDevice/src/SuplaDevice.cpp | 1104 ++-- lib/SuplaDevice/src/SuplaDevice.h | 254 +- lib/SuplaDevice/src/supla-common/lck.c | 400 +- lib/SuplaDevice/src/supla-common/lck.h | 126 +- lib/SuplaDevice/src/supla-common/log.h | 142 +- lib/SuplaDevice/src/supla-common/proto.c | 820 +-- lib/SuplaDevice/src/supla-common/proto.h | 3822 +++++------ lib/SuplaDevice/src/supla-common/srpc.c | 5856 ++++++++--------- lib/SuplaDevice/src/supla-common/srpc.h | 870 +-- lib/SuplaDevice/src/supla/action_handler.cpp | 54 +- lib/SuplaDevice/src/supla/action_handler.h | 62 +- lib/SuplaDevice/src/supla/actions.h | 190 +- lib/SuplaDevice/src/supla/at_channel.cpp | 146 +- lib/SuplaDevice/src/supla/at_channel.h | 78 +- lib/SuplaDevice/src/supla/channel.cpp | 784 +-- lib/SuplaDevice/src/supla/channel.h | 188 +- lib/SuplaDevice/src/supla/channel_element.cpp | 90 +- lib/SuplaDevice/src/supla/channel_element.h | 100 +- lib/SuplaDevice/src/supla/channel_extended.h | 68 +- lib/SuplaDevice/src/supla/condition.cpp | 262 +- lib/SuplaDevice/src/supla/condition.h | 148 +- .../src/supla/condition_getter.cpp | 580 +- lib/SuplaDevice/src/supla/condition_getter.h | 96 +- .../src/supla/conditions/on_between.cpp | 94 +- .../src/supla/conditions/on_between_eq.cpp | 94 +- .../src/supla/conditions/on_equal.cpp | 78 +- .../src/supla/conditions/on_greater.cpp | 80 +- .../src/supla/conditions/on_greater_eq.cpp | 76 +- .../src/supla/conditions/on_invalid.cpp | 86 +- .../src/supla/conditions/on_less.cpp | 80 +- .../src/supla/conditions/on_less_eq.cpp | 78 +- .../src/supla/control/action_trigger.cpp | 522 +- .../src/supla/control/action_trigger.h | 140 +- lib/SuplaDevice/src/supla/control/button.cpp | 336 +- lib/SuplaDevice/src/supla/control/button.h | 98 +- .../src/supla/control/roller_shutter.cpp | 1036 +-- .../src/supla/control/simple_button.cpp | 216 +- lib/SuplaDevice/src/supla/element.cpp | 302 +- lib/SuplaDevice/src/supla/element.h | 192 +- lib/SuplaDevice/src/supla/local_action.cpp | 292 +- lib/SuplaDevice/src/supla/local_action.h | 96 +- lib/SuplaDevice/src/supla/network/network.cpp | 470 +- lib/SuplaDevice/src/supla/pv/solaredge.cpp | 772 +-- lib/SuplaDevice/src/supla/sensor/SHT3x.h | 186 +- .../src/supla/sensor/electricity_meter.cpp | 548 +- .../src/supla/sensor/electricity_meter.h | 230 +- .../supla/sensor/therm_hygro_press_meter.cpp | 162 +- .../supla/sensor/therm_hygro_press_meter.h | 96 +- platformio.ini | 362 +- src/GUI-Generic.ino | 920 +-- src/Markup.cpp | 1062 +-- src/Markup.h | 246 +- src/SuplaCommonPROGMEM.h | 1000 +-- src/SuplaConfigESP.cpp | 1560 ++--- src/SuplaConfigESP.h | 336 +- src/SuplaDeviceGUI.cpp | 1178 ++-- src/SuplaDeviceGUI.h | 480 +- src/SuplaWebPageControl.cpp | 806 +-- src/SuplaWebPageLimitSwitch.cpp | 208 +- src/SuplaWebPageOther.cpp | 1070 +-- src/SuplaWebPageRelay.cpp | 1048 +-- src/SuplaWebPageSensor1Wire.cpp | 534 +- src/SuplaWebServer.cpp | 614 +- src/language/pl.h | 394 +- 82 files changed, 20769 insertions(+), 20769 deletions(-) diff --git a/lib/SuplaDevice/extras/test/ActionTriggerTests/action_trigger_tests.cpp b/lib/SuplaDevice/extras/test/ActionTriggerTests/action_trigger_tests.cpp index 1660e897..c8cdbb92 100644 --- a/lib/SuplaDevice/extras/test/ActionTriggerTests/action_trigger_tests.cpp +++ b/lib/SuplaDevice/extras/test/ActionTriggerTests/action_trigger_tests.cpp @@ -1,319 +1,319 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using testing::ElementsAreArray; -using testing::_; - -class ActionTriggerTests : public ::testing::Test { - protected: - virtual void SetUp() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - virtual void TearDown() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - -}; - -class ActionHandlerMock : public Supla::ActionHandler { - public: - MOCK_METHOD(void, handleAction, (int, int), (override)); -}; - -class TimeInterfaceStub : public TimeInterface { - public: - virtual unsigned long millis() override { - static unsigned long value = 0; - value += 1000; - return value; - } -}; - -TEST_F(ActionTriggerTests, AttachToMonostableButton) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Control::Button b1(10); - Supla::Control::ActionTrigger at; - ActionHandlerMock ah; - - at.attach(b1); - at.iterateConnected(0); - - b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_1); - b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_3); - b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_5); - b1.addAction(Supla::TURN_ON, ah, Supla::ON_HOLD); - - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_SHORT_PRESS_x1)); - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_HOLD)); - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_SHORT_PRESS_x5)); - - EXPECT_CALL(ah, handleAction(_, 0)).Times(4); - - EXPECT_FALSE(b1.isBistable()); - b1.runAction(Supla::ON_PRESS); - b1.runAction(Supla::ON_CLICK_1); - b1.runAction(Supla::ON_HOLD); - b1.runAction(Supla::ON_CLICK_6); - b1.runAction(Supla::ON_CLICK_5); - - for (int i = 0; i < 10; i++) { - at.iterateConnected(0); - } - - at.onInit(); - - TSD_ChannelConfig result = {}; - result.ConfigType = 0; - result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); - TSD_ChannelConfig_ActionTrigger config = {}; - config.ActiveActions = SUPLA_ACTION_CAP_HOLD - | SUPLA_ACTION_CAP_SHORT_PRESS_x1 - | SUPLA_ACTION_CAP_SHORT_PRESS_x2 - | SUPLA_ACTION_CAP_SHORT_PRESS_x3 - | SUPLA_ACTION_CAP_SHORT_PRESS_x4 - | SUPLA_ACTION_CAP_SHORT_PRESS_x5; - - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - - at.handleChannelConfig(&result); - b1.runAction(Supla::ON_PRESS); - b1.runAction(Supla::ON_CLICK_1); - b1.runAction(Supla::ON_HOLD); - b1.runAction(Supla::ON_CLICK_6); - b1.runAction(Supla::ON_CLICK_5); - - for (int i = 0; i < 10; i++) { - at.iterateConnected(0); - } - - TActionTriggerProperties *propInRegister = - reinterpret_cast - (Supla::Channel::reg_dev.channels[at.getChannelNumber()].value); - - EXPECT_EQ(propInRegister->relatedChannelNumber, 0); - EXPECT_EQ(propInRegister->disablesLocalOperation, - SUPLA_ACTION_CAP_HOLD - | SUPLA_ACTION_CAP_SHORT_PRESS_x1 - | SUPLA_ACTION_CAP_SHORT_PRESS_x3 - | SUPLA_ACTION_CAP_SHORT_PRESS_x5 - ); - - // another config from server which disables some actions - config.ActiveActions = SUPLA_ACTION_CAP_HOLD - | SUPLA_ACTION_CAP_SHORT_PRESS_x2 - | SUPLA_ACTION_CAP_SHORT_PRESS_x5; - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - at.handleChannelConfig(&result); - - // it should be executed on ah mock - b1.runAction(Supla::ON_CLICK_1); -} - -TEST_F(ActionTriggerTests, AttachToBistableButton) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Control::Button b1(10); - // enabling bistable button - b1.setMulticlickTime(500, true); - Supla::Control::ActionTrigger at; - Supla::Channel ch1; - Supla::Control::VirtualRelay relay1(1); - - at.attach(b1); - at.iterateConnected(0); - at.setRelatedChannel(ch1); - - b1.addAction(Supla::TURN_ON, relay1, Supla::ON_CLICK_1); - - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TOGGLE_x1)); - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TOGGLE_x5)); - - EXPECT_TRUE(b1.isBistable()); - b1.runAction(Supla::ON_PRESS); - b1.runAction(Supla::ON_CLICK_1); - b1.runAction(Supla::ON_HOLD); - b1.runAction(Supla::ON_CLICK_6); - b1.runAction(Supla::ON_CLICK_5); - - for (int i = 0; i < 10; i++) { - at.iterateConnected(0); - } - - at.onInit(); - - TSD_ChannelConfig result = {}; - result.ConfigType = 0; - result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); - TSD_ChannelConfig_ActionTrigger config = {}; - config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON - | SUPLA_ACTION_CAP_TURN_OFF - | SUPLA_ACTION_CAP_TOGGLE_x1 - | SUPLA_ACTION_CAP_TOGGLE_x2 - | SUPLA_ACTION_CAP_TOGGLE_x3 - | SUPLA_ACTION_CAP_TOGGLE_x4 - | SUPLA_ACTION_CAP_TOGGLE_x5; - - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - - at.handleChannelConfig(&result); - b1.runAction(Supla::ON_PRESS); - b1.runAction(Supla::ON_CLICK_1); - b1.runAction(Supla::ON_HOLD); - b1.runAction(Supla::ON_CLICK_6); - b1.runAction(Supla::ON_CLICK_5); - - for (int i = 0; i < 10; i++) { - at.iterateConnected(0); - } - - TActionTriggerProperties *propInRegister = - reinterpret_cast - (Supla::Channel::reg_dev.channels[at.getChannelNumber()].value); - - EXPECT_EQ(propInRegister->relatedChannelNumber, 2); - EXPECT_EQ(propInRegister->disablesLocalOperation, SUPLA_ACTION_CAP_TOGGLE_x1); - -} - -TEST_F(ActionTriggerTests, SendActionOnce) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Control::ActionTrigger at; - Supla::Control::ActionTrigger at2; - - TSD_ChannelConfig result = {}; - result.ConfigType = 0; - result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); - TSD_ChannelConfig_ActionTrigger config = {}; - config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON; - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - - at.handleChannelConfig(&result); - - config.ActiveActions = SUPLA_ACTION_CAP_SHORT_PRESS_x1; - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - - at2.handleChannelConfig(&result); - - at.iterateConnected(0); - - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); - EXPECT_CALL(srpc, actionTrigger(1, SUPLA_ACTION_CAP_SHORT_PRESS_x1)); - - at.handleAction(0, Supla::SEND_AT_TURN_ON); - - at.iterateConnected(0); - at.iterateConnected(0); - at.iterateConnected(0); - - at2.iterateConnected(0); - at2.handleAction(0, Supla::SEND_AT_SHORT_PRESS_x1); - - at2.iterateConnected(0); - at2.iterateConnected(0); -} - -TEST_F(ActionTriggerTests, SendFewActions) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Control::ActionTrigger at; - - TSD_ChannelConfig result = {}; - result.ConfigType = 0; - result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); - TSD_ChannelConfig_ActionTrigger config = {}; - config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON; - memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); - - at.iterateConnected(0); - at.handleChannelConfig(&result); - - EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); - - // activated action - at.handleAction(0, Supla::SEND_AT_TURN_ON); - - // not activated action - should be ignored - at.handleAction(0, Supla::SEND_AT_SHORT_PRESS_x2); - - at.iterateConnected(0); - at.iterateConnected(0); - at.iterateConnected(0); -} - -TEST_F(ActionTriggerTests, ActionsShouldAddCaps) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Control::ActionTrigger at; - Supla::Control::Button button(10, false, false); - - EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), 0); - - button.addAction(Supla::SEND_AT_HOLD, at, Supla::ON_PRESS); - EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), SUPLA_ACTION_CAP_HOLD); - - button.addAction(Supla::SEND_AT_TOGGLE_x2, at, Supla::ON_PRESS); - EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), - SUPLA_ACTION_CAP_HOLD | SUPLA_ACTION_CAP_TOGGLE_x2); - - button.addAction(Supla::SEND_AT_SHORT_PRESS_x5, at, Supla::ON_PRESS); - EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), - SUPLA_ACTION_CAP_HOLD | SUPLA_ACTION_CAP_TOGGLE_x2 | - SUPLA_ACTION_CAP_SHORT_PRESS_x5); -} - -TEST_F(ActionTriggerTests, RelatedChannel) { - SrpcMock srpc; - TimeInterfaceStub time; - Supla::Channel ch0; - Supla::ChannelElement che1; - Supla::Channel ch2; - Supla::Channel ch3; - Supla::ChannelElement che4; - Supla::Control::ActionTrigger at; - - EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 0); - - at.setRelatedChannel(&che4); - EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 5); - - at.setRelatedChannel(&ch0); - EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 1); - - at.setRelatedChannel(ch3); - EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 4); - - at.setRelatedChannel(che1); - EXPECT_EQ(che1.getChannelNumber(), 1); - EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 2); - -} - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using testing::ElementsAreArray; +using testing::_; + +class ActionTriggerTests : public ::testing::Test { + protected: + virtual void SetUp() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + virtual void TearDown() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + +}; + +class ActionHandlerMock : public Supla::ActionHandler { + public: + MOCK_METHOD(void, handleAction, (int, int), (override)); +}; + +class TimeInterfaceStub : public TimeInterface { + public: + virtual unsigned long millis() override { + static unsigned long value = 0; + value += 1000; + return value; + } +}; + +TEST_F(ActionTriggerTests, AttachToMonostableButton) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Control::Button b1(10); + Supla::Control::ActionTrigger at; + ActionHandlerMock ah; + + at.attach(b1); + at.iterateConnected(0); + + b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_1); + b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_3); + b1.addAction(Supla::TURN_ON, ah, Supla::ON_CLICK_5); + b1.addAction(Supla::TURN_ON, ah, Supla::ON_HOLD); + + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_SHORT_PRESS_x1)); + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_HOLD)); + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_SHORT_PRESS_x5)); + + EXPECT_CALL(ah, handleAction(_, 0)).Times(4); + + EXPECT_FALSE(b1.isBistable()); + b1.runAction(Supla::ON_PRESS); + b1.runAction(Supla::ON_CLICK_1); + b1.runAction(Supla::ON_HOLD); + b1.runAction(Supla::ON_CLICK_6); + b1.runAction(Supla::ON_CLICK_5); + + for (int i = 0; i < 10; i++) { + at.iterateConnected(0); + } + + at.onInit(); + + TSD_ChannelConfig result = {}; + result.ConfigType = 0; + result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); + TSD_ChannelConfig_ActionTrigger config = {}; + config.ActiveActions = SUPLA_ACTION_CAP_HOLD + | SUPLA_ACTION_CAP_SHORT_PRESS_x1 + | SUPLA_ACTION_CAP_SHORT_PRESS_x2 + | SUPLA_ACTION_CAP_SHORT_PRESS_x3 + | SUPLA_ACTION_CAP_SHORT_PRESS_x4 + | SUPLA_ACTION_CAP_SHORT_PRESS_x5; + + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + + at.handleChannelConfig(&result); + b1.runAction(Supla::ON_PRESS); + b1.runAction(Supla::ON_CLICK_1); + b1.runAction(Supla::ON_HOLD); + b1.runAction(Supla::ON_CLICK_6); + b1.runAction(Supla::ON_CLICK_5); + + for (int i = 0; i < 10; i++) { + at.iterateConnected(0); + } + + TActionTriggerProperties *propInRegister = + reinterpret_cast + (Supla::Channel::reg_dev.channels[at.getChannelNumber()].value); + + EXPECT_EQ(propInRegister->relatedChannelNumber, 0); + EXPECT_EQ(propInRegister->disablesLocalOperation, + SUPLA_ACTION_CAP_HOLD + | SUPLA_ACTION_CAP_SHORT_PRESS_x1 + | SUPLA_ACTION_CAP_SHORT_PRESS_x3 + | SUPLA_ACTION_CAP_SHORT_PRESS_x5 + ); + + // another config from server which disables some actions + config.ActiveActions = SUPLA_ACTION_CAP_HOLD + | SUPLA_ACTION_CAP_SHORT_PRESS_x2 + | SUPLA_ACTION_CAP_SHORT_PRESS_x5; + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + at.handleChannelConfig(&result); + + // it should be executed on ah mock + b1.runAction(Supla::ON_CLICK_1); +} + +TEST_F(ActionTriggerTests, AttachToBistableButton) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Control::Button b1(10); + // enabling bistable button + b1.setMulticlickTime(500, true); + Supla::Control::ActionTrigger at; + Supla::Channel ch1; + Supla::Control::VirtualRelay relay1(1); + + at.attach(b1); + at.iterateConnected(0); + at.setRelatedChannel(ch1); + + b1.addAction(Supla::TURN_ON, relay1, Supla::ON_CLICK_1); + + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TOGGLE_x1)); + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TOGGLE_x5)); + + EXPECT_TRUE(b1.isBistable()); + b1.runAction(Supla::ON_PRESS); + b1.runAction(Supla::ON_CLICK_1); + b1.runAction(Supla::ON_HOLD); + b1.runAction(Supla::ON_CLICK_6); + b1.runAction(Supla::ON_CLICK_5); + + for (int i = 0; i < 10; i++) { + at.iterateConnected(0); + } + + at.onInit(); + + TSD_ChannelConfig result = {}; + result.ConfigType = 0; + result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); + TSD_ChannelConfig_ActionTrigger config = {}; + config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON + | SUPLA_ACTION_CAP_TURN_OFF + | SUPLA_ACTION_CAP_TOGGLE_x1 + | SUPLA_ACTION_CAP_TOGGLE_x2 + | SUPLA_ACTION_CAP_TOGGLE_x3 + | SUPLA_ACTION_CAP_TOGGLE_x4 + | SUPLA_ACTION_CAP_TOGGLE_x5; + + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + + at.handleChannelConfig(&result); + b1.runAction(Supla::ON_PRESS); + b1.runAction(Supla::ON_CLICK_1); + b1.runAction(Supla::ON_HOLD); + b1.runAction(Supla::ON_CLICK_6); + b1.runAction(Supla::ON_CLICK_5); + + for (int i = 0; i < 10; i++) { + at.iterateConnected(0); + } + + TActionTriggerProperties *propInRegister = + reinterpret_cast + (Supla::Channel::reg_dev.channels[at.getChannelNumber()].value); + + EXPECT_EQ(propInRegister->relatedChannelNumber, 2); + EXPECT_EQ(propInRegister->disablesLocalOperation, SUPLA_ACTION_CAP_TOGGLE_x1); + +} + +TEST_F(ActionTriggerTests, SendActionOnce) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Control::ActionTrigger at; + Supla::Control::ActionTrigger at2; + + TSD_ChannelConfig result = {}; + result.ConfigType = 0; + result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); + TSD_ChannelConfig_ActionTrigger config = {}; + config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON; + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + + at.handleChannelConfig(&result); + + config.ActiveActions = SUPLA_ACTION_CAP_SHORT_PRESS_x1; + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + + at2.handleChannelConfig(&result); + + at.iterateConnected(0); + + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); + EXPECT_CALL(srpc, actionTrigger(1, SUPLA_ACTION_CAP_SHORT_PRESS_x1)); + + at.handleAction(0, Supla::SEND_AT_TURN_ON); + + at.iterateConnected(0); + at.iterateConnected(0); + at.iterateConnected(0); + + at2.iterateConnected(0); + at2.handleAction(0, Supla::SEND_AT_SHORT_PRESS_x1); + + at2.iterateConnected(0); + at2.iterateConnected(0); +} + +TEST_F(ActionTriggerTests, SendFewActions) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Control::ActionTrigger at; + + TSD_ChannelConfig result = {}; + result.ConfigType = 0; + result.ConfigSize = sizeof(TSD_ChannelConfig_ActionTrigger); + TSD_ChannelConfig_ActionTrigger config = {}; + config.ActiveActions = SUPLA_ACTION_CAP_TURN_ON; + memcpy(result.Config, &config, sizeof(TSD_ChannelConfig_ActionTrigger)); + + at.iterateConnected(0); + at.handleChannelConfig(&result); + + EXPECT_CALL(srpc, actionTrigger(0, SUPLA_ACTION_CAP_TURN_ON)); + + // activated action + at.handleAction(0, Supla::SEND_AT_TURN_ON); + + // not activated action - should be ignored + at.handleAction(0, Supla::SEND_AT_SHORT_PRESS_x2); + + at.iterateConnected(0); + at.iterateConnected(0); + at.iterateConnected(0); +} + +TEST_F(ActionTriggerTests, ActionsShouldAddCaps) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Control::ActionTrigger at; + Supla::Control::Button button(10, false, false); + + EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), 0); + + button.addAction(Supla::SEND_AT_HOLD, at, Supla::ON_PRESS); + EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), SUPLA_ACTION_CAP_HOLD); + + button.addAction(Supla::SEND_AT_TOGGLE_x2, at, Supla::ON_PRESS); + EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), + SUPLA_ACTION_CAP_HOLD | SUPLA_ACTION_CAP_TOGGLE_x2); + + button.addAction(Supla::SEND_AT_SHORT_PRESS_x5, at, Supla::ON_PRESS); + EXPECT_EQ(at.getChannel()->getActionTriggerCaps(), + SUPLA_ACTION_CAP_HOLD | SUPLA_ACTION_CAP_TOGGLE_x2 | + SUPLA_ACTION_CAP_SHORT_PRESS_x5); +} + +TEST_F(ActionTriggerTests, RelatedChannel) { + SrpcMock srpc; + TimeInterfaceStub time; + Supla::Channel ch0; + Supla::ChannelElement che1; + Supla::Channel ch2; + Supla::Channel ch3; + Supla::ChannelElement che4; + Supla::Control::ActionTrigger at; + + EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 0); + + at.setRelatedChannel(&che4); + EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 5); + + at.setRelatedChannel(&ch0); + EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 1); + + at.setRelatedChannel(ch3); + EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 4); + + at.setRelatedChannel(che1); + EXPECT_EQ(che1.getChannelNumber(), 1); + EXPECT_EQ((Supla::Channel::reg_dev.channels)[at.getChannelNumber()].value[0], 2); + +} + + diff --git a/lib/SuplaDevice/extras/test/CMakeLists.txt b/lib/SuplaDevice/extras/test/CMakeLists.txt index 6c5f4475..4aaf92d2 100644 --- a/lib/SuplaDevice/extras/test/CMakeLists.txt +++ b/lib/SuplaDevice/extras/test/CMakeLists.txt @@ -1,65 +1,65 @@ -cmake_minimum_required(VERSION 3.11) - -project(supladevice) - -enable_testing() - -set(CMAKE_CXX_STANDARD 14) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set(CMAKE_BUILD_TYPE Debug) - -include_directories(../../src) -include_directories(doubles) - -add_subdirectory(../../src/ build) - -mark_as_advanced( -BUILD_GMOCK -BUILD_GTEST -) - -include(FetchContent) - -FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG origin/master - ) - -FetchContent_GetProperties(googletest) -if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) -endif() - -file(GLOB TEST_SRC - UptimeTests/*.cpp - ChannelTests/*cpp - IoTests/*.cpp - ElementTests/*.cpp - LocalActionTests/*.cpp - SensorTests/*.cpp - ChannelElementTests/*.cpp - InternalPinOutputTests/*.cpp - PinStatusLedTests/*.cpp - ConditionTests/*.cpp - RgbwDimmerTests/*.cpp - ButtonTests/*.cpp - SuplaDeviceTests/*.cpp - CorrectionTests/*cpp - ActionTriggerTests/*cpp - ) - -file(GLOB DOUBLE_SRC doubles/*.cpp) - -add_executable(supladevicetests ${TEST_SRC} ${DOUBLE_SRC}) - -target_link_libraries(supladevicetests - gmock - gtest - gtest_main - supladevicelib - ) - -add_test(NAME supladevicetests - COMMAND supladevicetests) +cmake_minimum_required(VERSION 3.11) + +project(supladevice) + +enable_testing() + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +set(CMAKE_BUILD_TYPE Debug) + +include_directories(../../src) +include_directories(doubles) + +add_subdirectory(../../src/ build) + +mark_as_advanced( +BUILD_GMOCK +BUILD_GTEST +) + +include(FetchContent) + +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG origin/master + ) + +FetchContent_GetProperties(googletest) +if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) +endif() + +file(GLOB TEST_SRC + UptimeTests/*.cpp + ChannelTests/*cpp + IoTests/*.cpp + ElementTests/*.cpp + LocalActionTests/*.cpp + SensorTests/*.cpp + ChannelElementTests/*.cpp + InternalPinOutputTests/*.cpp + PinStatusLedTests/*.cpp + ConditionTests/*.cpp + RgbwDimmerTests/*.cpp + ButtonTests/*.cpp + SuplaDeviceTests/*.cpp + CorrectionTests/*cpp + ActionTriggerTests/*cpp + ) + +file(GLOB DOUBLE_SRC doubles/*.cpp) + +add_executable(supladevicetests ${TEST_SRC} ${DOUBLE_SRC}) + +target_link_libraries(supladevicetests + gmock + gtest + gtest_main + supladevicelib + ) + +add_test(NAME supladevicetests + COMMAND supladevicetests) diff --git a/lib/SuplaDevice/extras/test/ChannelElementTests/channel_element_tests.cpp b/lib/SuplaDevice/extras/test/ChannelElementTests/channel_element_tests.cpp index ed312cd8..a586eacf 100644 --- a/lib/SuplaDevice/extras/test/ChannelElementTests/channel_element_tests.cpp +++ b/lib/SuplaDevice/extras/test/ChannelElementTests/channel_element_tests.cpp @@ -1,87 +1,87 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include - - -class ActionHandlerMock : public Supla::ActionHandler { - public: - MOCK_METHOD(void, handleAction, (int, int), (override)); -}; - - -TEST(ChannelElementTests, ActionDelegationToChannel) { - ASSERT_EQ(Supla::LocalAction::getClientListPtr(), nullptr); - Supla::ChannelElement element; - - ActionHandlerMock mock1; - ActionHandlerMock mock2; - - int action1 = 11; - - EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)).Times(2); - EXPECT_CALL(mock2, handleAction(Supla::ON_TURN_OFF, action1)).Times(2); - - EXPECT_FALSE(element.isEventAlreadyUsed(Supla::ON_TURN_ON)); - EXPECT_FALSE(element.isEventAlreadyUsed(Supla::ON_TURN_OFF)); - - element.addAction(action1, mock1, Supla::ON_TURN_ON); - element.addAction(action1, &mock2, Supla::ON_TURN_OFF); - - EXPECT_TRUE(element.isEventAlreadyUsed(Supla::ON_TURN_ON)); - EXPECT_TRUE(element.isEventAlreadyUsed(Supla::ON_TURN_OFF)); - - element.getChannel()->setNewValue(false); - element.getChannel()->setNewValue(true); - element.getChannel()->setNewValue(true); - - element.getChannel()->setNewValue(false); - element.getChannel()->setNewValue(true); - element.getChannel()->setNewValue(false); - element.getChannel()->setNewValue(false); -} - -TEST(ChannelElementTests, ActionDelegationToConditions) { - ASSERT_EQ(Supla::LocalAction::getClientListPtr(), nullptr); - - ActionHandlerMock mock1; - ActionHandlerMock mock2; - - int action1 = 11; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)).Times(1); - EXPECT_CALL(mock2, handleAction(Supla::ON_CHANGE, action1)).Times(1); - - Supla::ChannelElement element; - auto channel = element.getChannel(); - channel->setType(SUPLA_CHANNELTYPE_DISTANCESENSOR); - - element.addAction(action1, mock1, OnLess(50)); - element.addAction(action1, &mock2, OnLess(30)); - - channel->setNewValue(60); - channel->setNewValue(50); - channel->setNewValue(45); - channel->setNewValue(25); -} - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + + +class ActionHandlerMock : public Supla::ActionHandler { + public: + MOCK_METHOD(void, handleAction, (int, int), (override)); +}; + + +TEST(ChannelElementTests, ActionDelegationToChannel) { + ASSERT_EQ(Supla::LocalAction::getClientListPtr(), nullptr); + Supla::ChannelElement element; + + ActionHandlerMock mock1; + ActionHandlerMock mock2; + + int action1 = 11; + + EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)).Times(2); + EXPECT_CALL(mock2, handleAction(Supla::ON_TURN_OFF, action1)).Times(2); + + EXPECT_FALSE(element.isEventAlreadyUsed(Supla::ON_TURN_ON)); + EXPECT_FALSE(element.isEventAlreadyUsed(Supla::ON_TURN_OFF)); + + element.addAction(action1, mock1, Supla::ON_TURN_ON); + element.addAction(action1, &mock2, Supla::ON_TURN_OFF); + + EXPECT_TRUE(element.isEventAlreadyUsed(Supla::ON_TURN_ON)); + EXPECT_TRUE(element.isEventAlreadyUsed(Supla::ON_TURN_OFF)); + + element.getChannel()->setNewValue(false); + element.getChannel()->setNewValue(true); + element.getChannel()->setNewValue(true); + + element.getChannel()->setNewValue(false); + element.getChannel()->setNewValue(true); + element.getChannel()->setNewValue(false); + element.getChannel()->setNewValue(false); +} + +TEST(ChannelElementTests, ActionDelegationToConditions) { + ASSERT_EQ(Supla::LocalAction::getClientListPtr(), nullptr); + + ActionHandlerMock mock1; + ActionHandlerMock mock2; + + int action1 = 11; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)).Times(1); + EXPECT_CALL(mock2, handleAction(Supla::ON_CHANGE, action1)).Times(1); + + Supla::ChannelElement element; + auto channel = element.getChannel(); + channel->setType(SUPLA_CHANNELTYPE_DISTANCESENSOR); + + element.addAction(action1, mock1, OnLess(50)); + element.addAction(action1, &mock2, OnLess(30)); + + channel->setNewValue(60); + channel->setNewValue(50); + channel->setNewValue(45); + channel->setNewValue(25); +} + + diff --git a/lib/SuplaDevice/extras/test/ChannelTests/channel_tests.cpp b/lib/SuplaDevice/extras/test/ChannelTests/channel_tests.cpp index e2d1ae8d..c53359c4 100644 --- a/lib/SuplaDevice/extras/test/ChannelTests/channel_tests.cpp +++ b/lib/SuplaDevice/extras/test/ChannelTests/channel_tests.cpp @@ -1,512 +1,512 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include -#include -#include -#include -#include -#include - - -class ActionHandlerMock : public Supla::ActionHandler { - public: - MOCK_METHOD(void, handleAction, (int, int), (override)); -}; - - -using ::testing::_; -using ::testing::ElementsAreArray; -using ::testing::Args; -using ::testing::ElementsAre; - -TEST(ChannelTests, ChannelMethods) { - Supla::Channel first; - Supla::Channel second; - - EXPECT_EQ(first.getChannelNumber(), 0); - EXPECT_EQ(second.getChannelNumber(), 1); - - EXPECT_EQ(first.isExtended(), false); - EXPECT_EQ(first.isUpdateReady(), false); - EXPECT_EQ(first.getChannelType(), 0); - EXPECT_EQ(first.getExtValue(), nullptr); - - int number = first.getChannelNumber(); - char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; - EXPECT_EQ(number, Supla::Channel::reg_dev.channels[number].Number); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Type, 0); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].FuncList, 0); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Default, 0); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, emptyArray, SUPLA_CHANNELVALUE_SIZE)); - - first.setType(10); - EXPECT_EQ(first.getChannelType(), 10); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Type, 10); - - first.setDefault(14); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Default, 14); - - first.setFlag(2); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 2); - - first.setFlag(4); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 2 | 4); - - first.unsetFlag(2); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 4); - - first.unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, 4); - - first.setFuncList(11); - EXPECT_EQ(Supla::Channel::reg_dev.channels[number].FuncList, 11); - -} - -TEST(ChannelTests, SetNewValue) { - Supla::Channel channel; - int number = channel.getChannelNumber(); - char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; - - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, emptyArray, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_FALSE(channel.isUpdateReady()); - - char array[SUPLA_CHANNELVALUE_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7}; - channel.setNewValue(array); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - - channel.clearUpdateReady(); - EXPECT_FALSE(channel.isUpdateReady()); - - channel.setNewValue(array); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_FALSE(channel.isUpdateReady()); - - array[4] = 15; - channel.setNewValue(array); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - - ASSERT_EQ(sizeof(double), 8); - double temp = 3.1415; - channel.setNewValue(temp); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &temp, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - char arrayBool[SUPLA_CHANNELVALUE_SIZE] = {}; - arrayBool[0] = true; - channel.setNewValue(true); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, arrayBool, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - channel.setNewValue(false); - arrayBool[0] = false; - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, arrayBool, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - int value = 1234; - ASSERT_EQ(sizeof(int), 4); - channel.setNewValue(value); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &value, sizeof(int))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - unsigned _supla_int64_t value64 = 124346; - ASSERT_EQ(sizeof(value64), 8); - channel.setNewValue(value64); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &value64, sizeof(value64))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - double humi = 95.2234123; - temp = 23.443322; - - int expectedTemp = temp * 1000; - int expectedHumi = humi * 1000; - - channel.setNewValue(temp, humi); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedTemp, sizeof(expectedTemp))); - EXPECT_TRUE(0 == memcmp(&(Supla::Channel::reg_dev.channels[number].value[4]), &expectedHumi, sizeof(expectedHumi))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - // RGBW channel setting - channel.setNewValue(1, 2, 3, 4, 5); - char rgbwArray[SUPLA_CHANNELVALUE_SIZE] = {5, 4, 3, 2, 1, 0, 0, 0}; - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, rgbwArray, SUPLA_CHANNELVALUE_SIZE)); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - TElectricityMeter_ExtendedValue_V2 emVal = {}; - TElectricityMeter_Value expectedValue = {}; - - emVal.m_count = 1; - emVal.measured_values |= EM_VAR_FORWARD_ACTIVE_ENERGY; - emVal.total_forward_active_energy[0] = 1000; - emVal.total_forward_active_energy[1] = 2000; - emVal.total_forward_active_energy[2] = 4000; - - expectedValue.total_forward_active_energy = (1000 + 2000 + 4000) / 1000; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - emVal.measured_values |= EM_VAR_VOLTAGE; - emVal.m[0].voltage[0] = 10; - emVal.m[0].voltage[1] = 0; - emVal.m[0].voltage[2] = 0; - - expectedValue.flags = 0; - expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - emVal.m[0].voltage[0] = 0; - emVal.m[0].voltage[1] = 20; - emVal.m[0].voltage[2] = 0; - - expectedValue.flags = 0; - expectedValue.flags |= EM_VALUE_FLAG_PHASE2_ON; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - - emVal.m[0].voltage[0] = 0; - emVal.m[0].voltage[1] = 0; - emVal.m[0].voltage[2] = 300; - - expectedValue.flags = 0; - expectedValue.flags |= EM_VALUE_FLAG_PHASE3_ON; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - - emVal.m[0].voltage[0] = 10; - emVal.m[0].voltage[1] = 0; - emVal.m[0].voltage[2] = 540; - - expectedValue.flags = 0; - expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON | EM_VALUE_FLAG_PHASE3_ON; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); - - emVal.m[0].voltage[0] = 10; - emVal.m[0].voltage[1] = 230; - emVal.m[0].voltage[2] = 540; - - expectedValue.flags = 0; - expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON | EM_VALUE_FLAG_PHASE3_ON | EM_VALUE_FLAG_PHASE2_ON; - - channel.setNewValue(emVal); - EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); - EXPECT_TRUE(channel.isUpdateReady()); - channel.clearUpdateReady(); -} - -TEST(ChannelTests, ChannelValueGetters) { - Supla::Channel channel; - - EXPECT_DOUBLE_EQ(channel.getValueDouble(), 0); - - double pi = 3.1415; - channel.setNewValue(pi); - EXPECT_DOUBLE_EQ(channel.getValueDouble(), pi); - - double e = 2.71828; - channel.setNewValue(pi, e); - EXPECT_NEAR(channel.getValueDoubleFirst(), pi, 0.001); - EXPECT_NEAR(channel.getValueDoubleSecond(), e, 0.001); - - int valueInt = 2021; - channel.setNewValue(valueInt); - EXPECT_EQ(channel.getValueInt32(), valueInt); - - unsigned _supla_int64_t valueInt64 = 202013012021000; - channel.setNewValue(valueInt64); - EXPECT_EQ(channel.getValueInt64(), valueInt64); - - channel.setNewValue(true); - EXPECT_TRUE(channel.getValueBool()); - - channel.setNewValue(false); - EXPECT_FALSE(channel.getValueBool()); - - uint8_t red = 10, green = 20, blue = 30, colorBright = 50, bright = 90; - channel.setNewValue(red, green, blue, colorBright, bright); - EXPECT_EQ(channel.getValueRed(), red); - EXPECT_EQ(channel.getValueGreen(), green); - EXPECT_EQ(channel.getValueBlue(), blue); - EXPECT_EQ(channel.getValueColorBrightness(), colorBright); - EXPECT_EQ(channel.getValueBrightness(), bright); -} - -TEST(ChannelTests, SendUpdateTest) { - Supla::Channel channel; - ::testing::InSequence seq; - SrpcMock srpc; - - const char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; - char array[SUPLA_CHANNELVALUE_SIZE] = {}; - array[0] = 1; - - EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array), 0, 0)); - - EXPECT_FALSE(channel.isUpdateReady()); - channel.sendUpdate(nullptr); - channel.setNewValue(true); - EXPECT_TRUE(channel.isUpdateReady()); - channel.sendUpdate(nullptr); - EXPECT_FALSE(channel.isUpdateReady()); -} - -TEST(ChannelTests, BoolChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - int action2 = 12; - int action3 = 13; - - EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_OFF, action2)); - EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action3)); - EXPECT_CALL(mock2, handleAction).Times(0); - - - ch1.addAction(action1, mock1, Supla::ON_TURN_ON); - ch1.addAction(action2, mock1, Supla::ON_TURN_OFF); - - ch1.setNewValue(true); - ch1.setNewValue(false); - ch1.setNewValue(false); // nothing should be called on mocks - ch1.setNewValue(false); // nothing should be called on mocks - - ch1.addAction(action3, mock1, Supla::ON_CHANGE); - ch1.setNewValue(true); - ch1.setNewValue(true); // nothing should be called on mocks - ch1.setNewValue(true); // nothing should be called on mocks - -} - -TEST(ChannelTests, Int32ChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - int action2 = 12; - int action3 = 13; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock2, handleAction).Times(0); - - ch1.addAction(action1, mock1, Supla::ON_CHANGE); - - _supla_int_t value = 15; - - ch1.setNewValue(value); - ch1.setNewValue(value); - - value++; - ch1.setNewValue(value); - - value++; - ch1.setNewValue(value); - ch1.setNewValue(value); - ch1.setNewValue(value); -} - -TEST(ChannelTests, Int64ChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - int action2 = 12; - int action3 = 13; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock2, handleAction).Times(0); - - ch1.addAction(action1, mock1, Supla::ON_CHANGE); - - unsigned _supla_int64_t value = 15; - - ch1.setNewValue(value); - ch1.setNewValue(value); - - value++; - ch1.setNewValue(value); - - value++; - ch1.setNewValue(value); - ch1.setNewValue(value); - ch1.setNewValue(value); -} - -TEST(ChannelTests, DoubleChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock2, handleAction).Times(0); - - ch1.addAction(action1, mock1, Supla::ON_CHANGE); - - double value = 3.1415; - - ch1.setNewValue(value); - ch1.setNewValue(value); - - value += 1.2; - ch1.setNewValue(value); - - value += 1.2; - ch1.setNewValue(value); - ch1.setNewValue(value); - ch1.setNewValue(value); -} - -TEST(ChannelTests, DoubleFloatChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock2, handleAction).Times(0); - - ch1.addAction(action1, mock1, Supla::ON_CHANGE); - - float value1 = 3.1415; - float value2 = 2.5; - - ch1.setNewValue(value1, value2); - ch1.setNewValue(value1, value2); - - value1 += 1.2; - ch1.setNewValue(value1, value2); - - value2 += 1.2; - ch1.setNewValue(value1, value2); - ch1.setNewValue(value1, value2); - ch1.setNewValue(value1, value2); -} - -TEST(ChannelTests, RgbwChannelWithLocalActions) { - Supla::Channel ch1; - - ::testing::InSequence seq; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - SrpcMock srpc; - - int action1 = 11; - - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(mock2, handleAction).Times(0); - - ch1.addAction(action1, mock1, Supla::ON_CHANGE); - - ch1.setNewValue(10, 20, 30, 90, 80); - ch1.setNewValue(10, 20, 30, 90, 80); - - ch1.setNewValue(10, 21, 30, 90, 80); - ch1.setNewValue(10, 20, 30, 90, 81); - ch1.setNewValue(10, 20, 30, 90, 81); -} - -TEST(ChannelTests, SetNewValueWithCorrection) { - Supla::Channel channel1; - Supla::Channel channel2; - - EXPECT_DOUBLE_EQ(channel1.getValueDouble(), 0); - - double pi = 3.1415; - channel1.setNewValue(pi); - EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi); - - channel1.setCorrection(3); - EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi); - - // Now correction should be applied - channel1.setNewValue(pi); - EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi + 3); - - - double e = 2.71828; - - channel2.setCorrection(2, true); - - channel2.setNewValue(pi, e); - EXPECT_NEAR(channel2.getValueDoubleFirst(), pi, 0.001); - EXPECT_NEAR(channel2.getValueDoubleSecond(), e + 2, 0.001); // value with correction - - Supla::Correction::clear(); // cleanup -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include + + +class ActionHandlerMock : public Supla::ActionHandler { + public: + MOCK_METHOD(void, handleAction, (int, int), (override)); +}; + + +using ::testing::_; +using ::testing::ElementsAreArray; +using ::testing::Args; +using ::testing::ElementsAre; + +TEST(ChannelTests, ChannelMethods) { + Supla::Channel first; + Supla::Channel second; + + EXPECT_EQ(first.getChannelNumber(), 0); + EXPECT_EQ(second.getChannelNumber(), 1); + + EXPECT_EQ(first.isExtended(), false); + EXPECT_EQ(first.isUpdateReady(), false); + EXPECT_EQ(first.getChannelType(), 0); + EXPECT_EQ(first.getExtValue(), nullptr); + + int number = first.getChannelNumber(); + char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; + EXPECT_EQ(number, Supla::Channel::reg_dev.channels[number].Number); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Type, 0); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].FuncList, 0); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Default, 0); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, emptyArray, SUPLA_CHANNELVALUE_SIZE)); + + first.setType(10); + EXPECT_EQ(first.getChannelType(), 10); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Type, 10); + + first.setDefault(14); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Default, 14); + + first.setFlag(2); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 2); + + first.setFlag(4); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 2 | 4); + + first.unsetFlag(2); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, SUPLA_CHANNEL_FLAG_CHANNELSTATE | 4); + + first.unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].Flags, 4); + + first.setFuncList(11); + EXPECT_EQ(Supla::Channel::reg_dev.channels[number].FuncList, 11); + +} + +TEST(ChannelTests, SetNewValue) { + Supla::Channel channel; + int number = channel.getChannelNumber(); + char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; + + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, emptyArray, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_FALSE(channel.isUpdateReady()); + + char array[SUPLA_CHANNELVALUE_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7}; + channel.setNewValue(array); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + + channel.clearUpdateReady(); + EXPECT_FALSE(channel.isUpdateReady()); + + channel.setNewValue(array); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_FALSE(channel.isUpdateReady()); + + array[4] = 15; + channel.setNewValue(array); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, array, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + + ASSERT_EQ(sizeof(double), 8); + double temp = 3.1415; + channel.setNewValue(temp); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &temp, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + char arrayBool[SUPLA_CHANNELVALUE_SIZE] = {}; + arrayBool[0] = true; + channel.setNewValue(true); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, arrayBool, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + channel.setNewValue(false); + arrayBool[0] = false; + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, arrayBool, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + int value = 1234; + ASSERT_EQ(sizeof(int), 4); + channel.setNewValue(value); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &value, sizeof(int))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + unsigned _supla_int64_t value64 = 124346; + ASSERT_EQ(sizeof(value64), 8); + channel.setNewValue(value64); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &value64, sizeof(value64))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + double humi = 95.2234123; + temp = 23.443322; + + int expectedTemp = temp * 1000; + int expectedHumi = humi * 1000; + + channel.setNewValue(temp, humi); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedTemp, sizeof(expectedTemp))); + EXPECT_TRUE(0 == memcmp(&(Supla::Channel::reg_dev.channels[number].value[4]), &expectedHumi, sizeof(expectedHumi))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + // RGBW channel setting + channel.setNewValue(1, 2, 3, 4, 5); + char rgbwArray[SUPLA_CHANNELVALUE_SIZE] = {5, 4, 3, 2, 1, 0, 0, 0}; + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, rgbwArray, SUPLA_CHANNELVALUE_SIZE)); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + TElectricityMeter_ExtendedValue_V2 emVal = {}; + TElectricityMeter_Value expectedValue = {}; + + emVal.m_count = 1; + emVal.measured_values |= EM_VAR_FORWARD_ACTIVE_ENERGY; + emVal.total_forward_active_energy[0] = 1000; + emVal.total_forward_active_energy[1] = 2000; + emVal.total_forward_active_energy[2] = 4000; + + expectedValue.total_forward_active_energy = (1000 + 2000 + 4000) / 1000; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + emVal.measured_values |= EM_VAR_VOLTAGE; + emVal.m[0].voltage[0] = 10; + emVal.m[0].voltage[1] = 0; + emVal.m[0].voltage[2] = 0; + + expectedValue.flags = 0; + expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + emVal.m[0].voltage[0] = 0; + emVal.m[0].voltage[1] = 20; + emVal.m[0].voltage[2] = 0; + + expectedValue.flags = 0; + expectedValue.flags |= EM_VALUE_FLAG_PHASE2_ON; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + + emVal.m[0].voltage[0] = 0; + emVal.m[0].voltage[1] = 0; + emVal.m[0].voltage[2] = 300; + + expectedValue.flags = 0; + expectedValue.flags |= EM_VALUE_FLAG_PHASE3_ON; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + + emVal.m[0].voltage[0] = 10; + emVal.m[0].voltage[1] = 0; + emVal.m[0].voltage[2] = 540; + + expectedValue.flags = 0; + expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON | EM_VALUE_FLAG_PHASE3_ON; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); + + emVal.m[0].voltage[0] = 10; + emVal.m[0].voltage[1] = 230; + emVal.m[0].voltage[2] = 540; + + expectedValue.flags = 0; + expectedValue.flags |= EM_VALUE_FLAG_PHASE1_ON | EM_VALUE_FLAG_PHASE3_ON | EM_VALUE_FLAG_PHASE2_ON; + + channel.setNewValue(emVal); + EXPECT_TRUE(0 == memcmp(Supla::Channel::reg_dev.channels[number].value, &expectedValue, sizeof(expectedValue))); + EXPECT_TRUE(channel.isUpdateReady()); + channel.clearUpdateReady(); +} + +TEST(ChannelTests, ChannelValueGetters) { + Supla::Channel channel; + + EXPECT_DOUBLE_EQ(channel.getValueDouble(), 0); + + double pi = 3.1415; + channel.setNewValue(pi); + EXPECT_DOUBLE_EQ(channel.getValueDouble(), pi); + + double e = 2.71828; + channel.setNewValue(pi, e); + EXPECT_NEAR(channel.getValueDoubleFirst(), pi, 0.001); + EXPECT_NEAR(channel.getValueDoubleSecond(), e, 0.001); + + int valueInt = 2021; + channel.setNewValue(valueInt); + EXPECT_EQ(channel.getValueInt32(), valueInt); + + unsigned _supla_int64_t valueInt64 = 202013012021000; + channel.setNewValue(valueInt64); + EXPECT_EQ(channel.getValueInt64(), valueInt64); + + channel.setNewValue(true); + EXPECT_TRUE(channel.getValueBool()); + + channel.setNewValue(false); + EXPECT_FALSE(channel.getValueBool()); + + uint8_t red = 10, green = 20, blue = 30, colorBright = 50, bright = 90; + channel.setNewValue(red, green, blue, colorBright, bright); + EXPECT_EQ(channel.getValueRed(), red); + EXPECT_EQ(channel.getValueGreen(), green); + EXPECT_EQ(channel.getValueBlue(), blue); + EXPECT_EQ(channel.getValueColorBrightness(), colorBright); + EXPECT_EQ(channel.getValueBrightness(), bright); +} + +TEST(ChannelTests, SendUpdateTest) { + Supla::Channel channel; + ::testing::InSequence seq; + SrpcMock srpc; + + const char emptyArray[SUPLA_CHANNELVALUE_SIZE] = {}; + char array[SUPLA_CHANNELVALUE_SIZE] = {}; + array[0] = 1; + + EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array), 0, 0)); + + EXPECT_FALSE(channel.isUpdateReady()); + channel.sendUpdate(nullptr); + channel.setNewValue(true); + EXPECT_TRUE(channel.isUpdateReady()); + channel.sendUpdate(nullptr); + EXPECT_FALSE(channel.isUpdateReady()); +} + +TEST(ChannelTests, BoolChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + int action2 = 12; + int action3 = 13; + + EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_OFF, action2)); + EXPECT_CALL(mock1, handleAction(Supla::ON_TURN_ON, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action3)); + EXPECT_CALL(mock2, handleAction).Times(0); + + + ch1.addAction(action1, mock1, Supla::ON_TURN_ON); + ch1.addAction(action2, mock1, Supla::ON_TURN_OFF); + + ch1.setNewValue(true); + ch1.setNewValue(false); + ch1.setNewValue(false); // nothing should be called on mocks + ch1.setNewValue(false); // nothing should be called on mocks + + ch1.addAction(action3, mock1, Supla::ON_CHANGE); + ch1.setNewValue(true); + ch1.setNewValue(true); // nothing should be called on mocks + ch1.setNewValue(true); // nothing should be called on mocks + +} + +TEST(ChannelTests, Int32ChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + int action2 = 12; + int action3 = 13; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock2, handleAction).Times(0); + + ch1.addAction(action1, mock1, Supla::ON_CHANGE); + + _supla_int_t value = 15; + + ch1.setNewValue(value); + ch1.setNewValue(value); + + value++; + ch1.setNewValue(value); + + value++; + ch1.setNewValue(value); + ch1.setNewValue(value); + ch1.setNewValue(value); +} + +TEST(ChannelTests, Int64ChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + int action2 = 12; + int action3 = 13; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock2, handleAction).Times(0); + + ch1.addAction(action1, mock1, Supla::ON_CHANGE); + + unsigned _supla_int64_t value = 15; + + ch1.setNewValue(value); + ch1.setNewValue(value); + + value++; + ch1.setNewValue(value); + + value++; + ch1.setNewValue(value); + ch1.setNewValue(value); + ch1.setNewValue(value); +} + +TEST(ChannelTests, DoubleChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock2, handleAction).Times(0); + + ch1.addAction(action1, mock1, Supla::ON_CHANGE); + + double value = 3.1415; + + ch1.setNewValue(value); + ch1.setNewValue(value); + + value += 1.2; + ch1.setNewValue(value); + + value += 1.2; + ch1.setNewValue(value); + ch1.setNewValue(value); + ch1.setNewValue(value); +} + +TEST(ChannelTests, DoubleFloatChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock2, handleAction).Times(0); + + ch1.addAction(action1, mock1, Supla::ON_CHANGE); + + float value1 = 3.1415; + float value2 = 2.5; + + ch1.setNewValue(value1, value2); + ch1.setNewValue(value1, value2); + + value1 += 1.2; + ch1.setNewValue(value1, value2); + + value2 += 1.2; + ch1.setNewValue(value1, value2); + ch1.setNewValue(value1, value2); + ch1.setNewValue(value1, value2); +} + +TEST(ChannelTests, RgbwChannelWithLocalActions) { + Supla::Channel ch1; + + ::testing::InSequence seq; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + SrpcMock srpc; + + int action1 = 11; + + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock1, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(mock2, handleAction).Times(0); + + ch1.addAction(action1, mock1, Supla::ON_CHANGE); + + ch1.setNewValue(10, 20, 30, 90, 80); + ch1.setNewValue(10, 20, 30, 90, 80); + + ch1.setNewValue(10, 21, 30, 90, 80); + ch1.setNewValue(10, 20, 30, 90, 81); + ch1.setNewValue(10, 20, 30, 90, 81); +} + +TEST(ChannelTests, SetNewValueWithCorrection) { + Supla::Channel channel1; + Supla::Channel channel2; + + EXPECT_DOUBLE_EQ(channel1.getValueDouble(), 0); + + double pi = 3.1415; + channel1.setNewValue(pi); + EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi); + + channel1.setCorrection(3); + EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi); + + // Now correction should be applied + channel1.setNewValue(pi); + EXPECT_DOUBLE_EQ(channel1.getValueDouble(), pi + 3); + + + double e = 2.71828; + + channel2.setCorrection(2, true); + + channel2.setNewValue(pi, e); + EXPECT_NEAR(channel2.getValueDoubleFirst(), pi, 0.001); + EXPECT_NEAR(channel2.getValueDoubleSecond(), e + 2, 0.001); // value with correction + + Supla::Correction::clear(); // cleanup +} diff --git a/lib/SuplaDevice/extras/test/ConditionTests/em_getter_tests.cpp b/lib/SuplaDevice/extras/test/ConditionTests/em_getter_tests.cpp index 48e7b4a4..9523499a 100644 --- a/lib/SuplaDevice/extras/test/ConditionTests/em_getter_tests.cpp +++ b/lib/SuplaDevice/extras/test/ConditionTests/em_getter_tests.cpp @@ -1,422 +1,422 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include - -#include -#include -#include -#include - -using ::testing::_; -using ::testing::ElementsAreArray; -using ::testing::Args; -using ::testing::ElementsAre; - -TEST(EmGetterTests, VoltageGetter) { - auto getter = EmVoltage(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setVoltage(0, 220.5 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 220.5, 0.05); - EXPECT_TRUE(isValid); - - isValid = false; - em.setVoltage(0, 120 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 120, 0.05); - EXPECT_TRUE(isValid); - - isValid = false; - em.setVoltage(1, 320 * 100); // set voltage on another phase - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 120, 0.05); - EXPECT_TRUE(isValid); - - auto getterPhase2 = EmVoltage(1); - - EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 320, 0.05); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, CurrentGetter) { - auto getter = EmCurrent(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setCurrent(0, 12 * 1000); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 12.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setCurrent(0, 8.52 * 1000); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setCurrent(1, 66 * 1000); // set voltage on another phase - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - auto getterPhase2 = EmCurrent(1); - - EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, TotalCurrentGetter) { - auto getter = EmTotalCurrent(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setCurrent(0, 12 * 1000); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 12.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setCurrent(0, 8.52 * 1000); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setCurrent(1, 66 * 1000); // set voltage on another phase - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, PowerActiveWGetter) { - auto getter = EmPowerActiveW(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerActive(0, 300 * 100); // 300 W - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerActive(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerActive(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - auto getterPhase2 = EmPowerActiveW(1); - - EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, TotalPowerActiveWGetter) { - auto getter = EmTotalPowerActiveW(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerActive(0, 300 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerActive(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerActive(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, PowerApparentGetter) { - auto getter = EmPowerApparentVA(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerApparent(0, 300 * 100); // 300 - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerApparent(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerApparent(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - auto getterPhase2 = EmPowerApparentVA(1); - - EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, TotalPowerApparentGetter) { - auto getter = EmTotalPowerApparentVA(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerApparent(0, 300 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerApparent(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerApparent(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, PowerReactiveGetter) { - auto getter = EmPowerReactiveVar(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerReactive(0, 300 * 100); // 300 W - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerReactive(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerReactive(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - auto getterPhase2 = EmPowerReactiveVar(1); - - EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); - EXPECT_TRUE(isValid); - -} - -TEST(EmGetterTests, TotalPowerReactiveGetter) { - auto getter = EmTotalPowerReactiveVar(); - - bool isValid = true; - EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Element element; - isValid = true; - EXPECT_EQ(getter->getValue(&element, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::ChannelElement chElement; - isValid = true; - EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); - EXPECT_FALSE(isValid); - - Supla::Sensor::ElectricityMeter em; - isValid = true; - EXPECT_EQ(getter->getValue(&em, isValid), 0.0); - EXPECT_FALSE(isValid); - - em.setPowerReactive(0, 300 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerReactive(0, 8.52 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); - EXPECT_TRUE(isValid); - - isValid = false; - em.setPowerReactive(1, 66 * 100); - em.updateChannelValues(); - EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); - EXPECT_TRUE(isValid); - -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include +#include +#include +#include + +using ::testing::_; +using ::testing::ElementsAreArray; +using ::testing::Args; +using ::testing::ElementsAre; + +TEST(EmGetterTests, VoltageGetter) { + auto getter = EmVoltage(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setVoltage(0, 220.5 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 220.5, 0.05); + EXPECT_TRUE(isValid); + + isValid = false; + em.setVoltage(0, 120 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 120, 0.05); + EXPECT_TRUE(isValid); + + isValid = false; + em.setVoltage(1, 320 * 100); // set voltage on another phase + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 120, 0.05); + EXPECT_TRUE(isValid); + + auto getterPhase2 = EmVoltage(1); + + EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 320, 0.05); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, CurrentGetter) { + auto getter = EmCurrent(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setCurrent(0, 12 * 1000); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 12.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setCurrent(0, 8.52 * 1000); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setCurrent(1, 66 * 1000); // set voltage on another phase + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + auto getterPhase2 = EmCurrent(1); + + EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, TotalCurrentGetter) { + auto getter = EmTotalCurrent(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setCurrent(0, 12 * 1000); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 12.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setCurrent(0, 8.52 * 1000); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setCurrent(1, 66 * 1000); // set voltage on another phase + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, PowerActiveWGetter) { + auto getter = EmPowerActiveW(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerActive(0, 300 * 100); // 300 W + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerActive(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerActive(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + auto getterPhase2 = EmPowerActiveW(1); + + EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, TotalPowerActiveWGetter) { + auto getter = EmTotalPowerActiveW(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerActive(0, 300 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerActive(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerActive(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, PowerApparentGetter) { + auto getter = EmPowerApparentVA(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerApparent(0, 300 * 100); // 300 + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerApparent(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerApparent(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + auto getterPhase2 = EmPowerApparentVA(1); + + EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, TotalPowerApparentGetter) { + auto getter = EmTotalPowerApparentVA(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerApparent(0, 300 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerApparent(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerApparent(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, PowerReactiveGetter) { + auto getter = EmPowerReactiveVar(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerReactive(0, 300 * 100); // 300 W + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerReactive(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerReactive(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + auto getterPhase2 = EmPowerReactiveVar(1); + + EXPECT_NEAR(getterPhase2->getValue(&em, isValid), 66, 0.05); + EXPECT_TRUE(isValid); + +} + +TEST(EmGetterTests, TotalPowerReactiveGetter) { + auto getter = EmTotalPowerReactiveVar(); + + bool isValid = true; + EXPECT_EQ(getter->getValue(nullptr, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Element element; + isValid = true; + EXPECT_EQ(getter->getValue(&element, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::ChannelElement chElement; + isValid = true; + EXPECT_EQ(getter->getValue(&chElement, isValid), 0.0); + EXPECT_FALSE(isValid); + + Supla::Sensor::ElectricityMeter em; + isValid = true; + EXPECT_EQ(getter->getValue(&em, isValid), 0.0); + EXPECT_FALSE(isValid); + + em.setPowerReactive(0, 300 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 300.0, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerReactive(0, 8.52 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52, 0.005); + EXPECT_TRUE(isValid); + + isValid = false; + em.setPowerReactive(1, 66 * 100); + em.updateChannelValues(); + EXPECT_NEAR(getter->getValue(&em, isValid), 8.52 + 66, 0.005); + EXPECT_TRUE(isValid); + +} diff --git a/lib/SuplaDevice/extras/test/ConditionTests/on_less_tests.cpp b/lib/SuplaDevice/extras/test/ConditionTests/on_less_tests.cpp index a30e2a32..5e906c3c 100644 --- a/lib/SuplaDevice/extras/test/ConditionTests/on_less_tests.cpp +++ b/lib/SuplaDevice/extras/test/ConditionTests/on_less_tests.cpp @@ -1,392 +1,392 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include - -#include -#include -#include -#include -#include - - -class ActionHandlerMock : public Supla::ActionHandler { - public: - MOCK_METHOD(void, handleAction, (int, int), (override)); -}; - - -using ::testing::_; -using ::testing::ElementsAreArray; -using ::testing::Args; -using ::testing::ElementsAre; - -TEST(ConditionTests, handleActionTestsForDouble) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)).Times(4); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)).Times(4); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - auto cond = OnLess(15.1); - cond->setSource(channelElement); - cond->setClient(ahMock); - - - channel->setType(SUPLA_CHANNELTYPE_WINDSENSOR); - - channel->setNewValue(0.0); - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - // 100 is not less than 15.1, so nothing should happen - channel->setNewValue(100.0); - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below 0 should be ignored - channel->setNewValue(-0.2); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.0); - // 15 is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); - - // nothing should happen - channel->setNewValue(25.0); - cond->handleAction(Supla::ON_CHANGE, action1); - - // PRESSURE sensor use int type on channel value - channel->setType(SUPLA_CHANNELTYPE_PRESSURESENSOR); - - channel->setNewValue(0.0); - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(100.0); - - // 100 is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below 0 should be ignored - channel->setNewValue(-0.2); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.0); - // 15 is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); - - // nothing should happen - channel->setNewValue(25.0); - cond->handleAction(Supla::ON_CHANGE, action1); - - // RAIN sensor use int type on channel value - channel->setType(SUPLA_CHANNELTYPE_RAINSENSOR); - - channel->setNewValue(0.0); - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(100.0); - - // 100 is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below 0 should be ignored - channel->setNewValue(-0.2); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.0); - // 15 is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); - - // nothing should happen - channel->setNewValue(25.0); - cond->handleAction(Supla::ON_CHANGE, action1); - - - // WEIGHT sensor use int type on channel value - channel->setType(SUPLA_CHANNELTYPE_WEIGHTSENSOR); - - channel->setNewValue(0.0); - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(100.0); - - // 100 is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below 0 should be ignored - channel->setNewValue(-0.2); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.0); - // 15 is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); - -} - -TEST(ConditionTests, handleActionTestsForInt64) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - auto cond = OnLess(15.1); - cond->setSource(channelElement); - cond->setClient(ahMock); - - channel->setType(SUPLA_CHANNELTYPE_IMPULSE_COUNTER); - - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - unsigned _supla_int64_t newValue = 10000344422234; - channel->setNewValue(newValue); - - // newValue is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - newValue = 2; - channel->setNewValue(newValue); - // newValue is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); -} - -TEST(ConditionTests, handleActionTestsForDouble2) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)).Times(2); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - auto cond = OnLess(15.1); - cond->setSource(channelElement); - cond->setClient(ahMock); - - channel->setType(SUPLA_CHANNELTYPE_THERMOMETER); - - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(15.1); - - // 15.1 is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below -273 should be ignored - channel->setNewValue(-275.0); - cond->handleAction(Supla::ON_CHANGE, action2); - - // going from "invalid" to valid value meeting contidion should trigger action - channel->setNewValue(-15.01); - cond->handleAction(Supla::ON_CHANGE, action3); - - // DISTANCE sensor use double type on channel value - channel->setType(SUPLA_CHANNELTYPE_DISTANCESENSOR); - - channel->setNewValue(100); - - // 100 is not less than 15.1, so nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below 0 should be ignored - channel->setNewValue(-0.2); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15); - // 15 is less than 15.1 - cond->handleAction(Supla::ON_CHANGE, action3); - - // nothing should happen - channel->setNewValue(25); - cond->handleAction(Supla::ON_CHANGE, action1); -} - -TEST(ConditionTests, handleActionTestsForNotSupportedChannel) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction).Times(0); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - auto cond = OnLess(15.1); - cond->setSource(channelElement); - cond->setClient(ahMock); - - // this channel type is not used in library. DS18B20 uses standard THERMOMETER channel - channel->setType(SUPLA_CHANNELTYPE_THERMOMETERDS18B20); - - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(15.1); - - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.01); - cond->handleAction(Supla::ON_CHANGE, action3); -} - -TEST(ConditionTests, handleActionTestsForFirstDouble) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - auto cond = OnLess(15.1); - cond->setSource(channelElement); - cond->setClient(ahMock); - - channel->setType(SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR); - - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(15.1, 10.5); - - // nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values below -273 should be ignored - channel->setNewValue(-275.0, 10.5); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.1, 100.5); - - // nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - - // ahMock should be called - channel->setNewValue(15.01, 25.1); - cond->handleAction(Supla::ON_CHANGE, action3); -} - -TEST(ConditionTests, handleActionTestsForSecondDouble) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); - - Supla::ChannelElement channelElement; - auto channel = channelElement.getChannel(); - - // second parameter indicates that we should check alternative channel value (pressure/second float) - auto cond = OnLess(15.1, true); - cond->setSource(channelElement); - cond->setClient(ahMock); - - channel->setType(SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR); - - // channel should be initialized to 0, so condition should be met - cond->handleAction(Supla::ON_CHANGE, action1); - - channel->setNewValue(0.1, 15.1); - - // nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - // Values of humidity below 0 should be ignored - channel->setNewValue(-5.0); - cond->handleAction(Supla::ON_CHANGE, action2); - - channel->setNewValue(15.1, 100.5); - - // nothing should happen - cond->handleAction(Supla::ON_CHANGE, action2); - - - // ahMock should be called - channel->setNewValue(16.01, 5.1); - cond->handleAction(Supla::ON_CHANGE, action3); -} - -TEST(OnLessTests, OnLessConditionTests) { - auto cond = OnLess(10); - - EXPECT_TRUE(cond->checkConditionFor(5)); - EXPECT_FALSE(cond->checkConditionFor(15)); - EXPECT_FALSE(cond->checkConditionFor(10)); - EXPECT_TRUE(cond->checkConditionFor(9.9999)); - - // "On" conditions should fire actions only on transition to meet condition. - EXPECT_FALSE(cond->checkConditionFor(5)); - EXPECT_FALSE(cond->checkConditionFor(5)); - EXPECT_FALSE(cond->checkConditionFor(5)); - - // Going back above threshold value, should reset expectation and it should return - // true on next call with met condition - EXPECT_FALSE(cond->checkConditionFor(50)); - EXPECT_TRUE(cond->checkConditionFor(5)); - -} - -TEST(ConditionTests, handleActionTestsWithCustomGetter) { - ActionHandlerMock ahMock; - const int action1 = 15; - const int action2 = 16; - const int action3 = 17; - - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); - EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); - - Supla::Sensor::ElectricityMeter em; - - em.addAction(action1, ahMock, OnLess(220.0, EmVoltage(0))); - em.addAction(action2, ahMock, OnLess(220.0, EmVoltage(1))); - em.addAction(action3, ahMock, OnLess(120.0, EmVoltage(0))); - - em.setVoltage(0, 230.0 * 100); - em.setVoltage(1, 233.0 * 100); - em.updateChannelValues(); - - em.setVoltage(0, 210.0 * 100); - em.updateChannelValues(); - - em.setVoltage(0, 110.0 * 100); - em.updateChannelValues(); - -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include +#include +#include +#include +#include + + +class ActionHandlerMock : public Supla::ActionHandler { + public: + MOCK_METHOD(void, handleAction, (int, int), (override)); +}; + + +using ::testing::_; +using ::testing::ElementsAreArray; +using ::testing::Args; +using ::testing::ElementsAre; + +TEST(ConditionTests, handleActionTestsForDouble) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)).Times(4); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)).Times(4); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + auto cond = OnLess(15.1); + cond->setSource(channelElement); + cond->setClient(ahMock); + + + channel->setType(SUPLA_CHANNELTYPE_WINDSENSOR); + + channel->setNewValue(0.0); + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + // 100 is not less than 15.1, so nothing should happen + channel->setNewValue(100.0); + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below 0 should be ignored + channel->setNewValue(-0.2); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.0); + // 15 is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); + + // nothing should happen + channel->setNewValue(25.0); + cond->handleAction(Supla::ON_CHANGE, action1); + + // PRESSURE sensor use int type on channel value + channel->setType(SUPLA_CHANNELTYPE_PRESSURESENSOR); + + channel->setNewValue(0.0); + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(100.0); + + // 100 is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below 0 should be ignored + channel->setNewValue(-0.2); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.0); + // 15 is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); + + // nothing should happen + channel->setNewValue(25.0); + cond->handleAction(Supla::ON_CHANGE, action1); + + // RAIN sensor use int type on channel value + channel->setType(SUPLA_CHANNELTYPE_RAINSENSOR); + + channel->setNewValue(0.0); + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(100.0); + + // 100 is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below 0 should be ignored + channel->setNewValue(-0.2); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.0); + // 15 is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); + + // nothing should happen + channel->setNewValue(25.0); + cond->handleAction(Supla::ON_CHANGE, action1); + + + // WEIGHT sensor use int type on channel value + channel->setType(SUPLA_CHANNELTYPE_WEIGHTSENSOR); + + channel->setNewValue(0.0); + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(100.0); + + // 100 is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below 0 should be ignored + channel->setNewValue(-0.2); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.0); + // 15 is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); + +} + +TEST(ConditionTests, handleActionTestsForInt64) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + auto cond = OnLess(15.1); + cond->setSource(channelElement); + cond->setClient(ahMock); + + channel->setType(SUPLA_CHANNELTYPE_IMPULSE_COUNTER); + + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + unsigned _supla_int64_t newValue = 10000344422234; + channel->setNewValue(newValue); + + // newValue is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + newValue = 2; + channel->setNewValue(newValue); + // newValue is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); +} + +TEST(ConditionTests, handleActionTestsForDouble2) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)).Times(2); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + auto cond = OnLess(15.1); + cond->setSource(channelElement); + cond->setClient(ahMock); + + channel->setType(SUPLA_CHANNELTYPE_THERMOMETER); + + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(15.1); + + // 15.1 is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below -273 should be ignored + channel->setNewValue(-275.0); + cond->handleAction(Supla::ON_CHANGE, action2); + + // going from "invalid" to valid value meeting contidion should trigger action + channel->setNewValue(-15.01); + cond->handleAction(Supla::ON_CHANGE, action3); + + // DISTANCE sensor use double type on channel value + channel->setType(SUPLA_CHANNELTYPE_DISTANCESENSOR); + + channel->setNewValue(100); + + // 100 is not less than 15.1, so nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below 0 should be ignored + channel->setNewValue(-0.2); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15); + // 15 is less than 15.1 + cond->handleAction(Supla::ON_CHANGE, action3); + + // nothing should happen + channel->setNewValue(25); + cond->handleAction(Supla::ON_CHANGE, action1); +} + +TEST(ConditionTests, handleActionTestsForNotSupportedChannel) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction).Times(0); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + auto cond = OnLess(15.1); + cond->setSource(channelElement); + cond->setClient(ahMock); + + // this channel type is not used in library. DS18B20 uses standard THERMOMETER channel + channel->setType(SUPLA_CHANNELTYPE_THERMOMETERDS18B20); + + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(15.1); + + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.01); + cond->handleAction(Supla::ON_CHANGE, action3); +} + +TEST(ConditionTests, handleActionTestsForFirstDouble) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + auto cond = OnLess(15.1); + cond->setSource(channelElement); + cond->setClient(ahMock); + + channel->setType(SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR); + + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(15.1, 10.5); + + // nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values below -273 should be ignored + channel->setNewValue(-275.0, 10.5); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.1, 100.5); + + // nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + + // ahMock should be called + channel->setNewValue(15.01, 25.1); + cond->handleAction(Supla::ON_CHANGE, action3); +} + +TEST(ConditionTests, handleActionTestsForSecondDouble) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); + + Supla::ChannelElement channelElement; + auto channel = channelElement.getChannel(); + + // second parameter indicates that we should check alternative channel value (pressure/second float) + auto cond = OnLess(15.1, true); + cond->setSource(channelElement); + cond->setClient(ahMock); + + channel->setType(SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR); + + // channel should be initialized to 0, so condition should be met + cond->handleAction(Supla::ON_CHANGE, action1); + + channel->setNewValue(0.1, 15.1); + + // nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + // Values of humidity below 0 should be ignored + channel->setNewValue(-5.0); + cond->handleAction(Supla::ON_CHANGE, action2); + + channel->setNewValue(15.1, 100.5); + + // nothing should happen + cond->handleAction(Supla::ON_CHANGE, action2); + + + // ahMock should be called + channel->setNewValue(16.01, 5.1); + cond->handleAction(Supla::ON_CHANGE, action3); +} + +TEST(OnLessTests, OnLessConditionTests) { + auto cond = OnLess(10); + + EXPECT_TRUE(cond->checkConditionFor(5)); + EXPECT_FALSE(cond->checkConditionFor(15)); + EXPECT_FALSE(cond->checkConditionFor(10)); + EXPECT_TRUE(cond->checkConditionFor(9.9999)); + + // "On" conditions should fire actions only on transition to meet condition. + EXPECT_FALSE(cond->checkConditionFor(5)); + EXPECT_FALSE(cond->checkConditionFor(5)); + EXPECT_FALSE(cond->checkConditionFor(5)); + + // Going back above threshold value, should reset expectation and it should return + // true on next call with met condition + EXPECT_FALSE(cond->checkConditionFor(50)); + EXPECT_TRUE(cond->checkConditionFor(5)); + +} + +TEST(ConditionTests, handleActionTestsWithCustomGetter) { + ActionHandlerMock ahMock; + const int action1 = 15; + const int action2 = 16; + const int action3 = 17; + + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action1)); + EXPECT_CALL(ahMock, handleAction(Supla::ON_CHANGE, action3)); + + Supla::Sensor::ElectricityMeter em; + + em.addAction(action1, ahMock, OnLess(220.0, EmVoltage(0))); + em.addAction(action2, ahMock, OnLess(220.0, EmVoltage(1))); + em.addAction(action3, ahMock, OnLess(120.0, EmVoltage(0))); + + em.setVoltage(0, 230.0 * 100); + em.setVoltage(1, 233.0 * 100); + em.updateChannelValues(); + + em.setVoltage(0, 210.0 * 100); + em.updateChannelValues(); + + em.setVoltage(0, 110.0 * 100); + em.updateChannelValues(); + +} diff --git a/lib/SuplaDevice/extras/test/ElementTests/element_tests.cpp b/lib/SuplaDevice/extras/test/ElementTests/element_tests.cpp index db03dc20..9d5ec53b 100644 --- a/lib/SuplaDevice/extras/test/ElementTests/element_tests.cpp +++ b/lib/SuplaDevice/extras/test/ElementTests/element_tests.cpp @@ -1,207 +1,207 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include -#include -#include -#include - -using ::testing::Return; -using ::testing::ElementsAreArray; - -class ElementTests : public ::testing::Test { - protected: - virtual void SetUp() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - virtual void TearDown() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - -}; - - -class ElementWithChannel : public Supla::Element { - public: - Supla::Channel *getChannel() { - return &channel; - } - Supla::Channel channel; -}; - -TEST_F(ElementTests, ElementEmptyListTests) { - EXPECT_EQ(Supla::Element::begin(), nullptr); - EXPECT_EQ(Supla::Element::last(), nullptr); - EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); - EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), nullptr); - EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); -} - -TEST_F(ElementTests, ElementListAdding) { - auto el1 = new Supla::Element; - - EXPECT_EQ(Supla::Element::begin(), el1); - EXPECT_EQ(Supla::Element::last(), el1); - - EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); - // Element without channel number acts as channel with -1 number - EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), el1); - EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); - - auto el2 = new Supla::Element; - EXPECT_EQ(Supla::Element::begin(), el1); - EXPECT_EQ(Supla::Element::last(), el2); - - EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); - // Element without channel number acts as channel with -1 number - EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), el1); - EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); - - auto el3 = new Supla::Element; - EXPECT_EQ(Supla::Element::begin(), el1); - EXPECT_EQ(Supla::Element::last(), el3); - - delete el2; - - EXPECT_EQ(Supla::Element::begin(), el1); - EXPECT_EQ(Supla::Element::last(), el3); - - el2 = new Supla::Element; - EXPECT_EQ(Supla::Element::begin(), el1); - EXPECT_EQ(Supla::Element::last(), el2); - - delete el1; - EXPECT_EQ(Supla::Element::begin(), el3); - EXPECT_EQ(Supla::Element::last(), el2); - - el1 = new Supla::Element; - EXPECT_EQ(Supla::Element::begin(), el3); - EXPECT_EQ(Supla::Element::last(), el1); - - delete el1; - EXPECT_EQ(Supla::Element::begin(), el3); - EXPECT_EQ(Supla::Element::last(), el2); - - delete el2; - delete el3; - - EXPECT_EQ(Supla::Element::begin(), nullptr); - EXPECT_EQ(Supla::Element::last(), nullptr); - -} - -TEST_F(ElementTests, NoChannelElementMethods) { - TimeInterfaceMock time; - Supla::Element el1; - - EXPECT_CALL(time, millis()).Times(2); - - // those methods are empty, so just call to make sure that they do nothing and don't crash - el1.onInit(); - el1.onLoadState(); - el1.onSaveState(); - el1.iterateAlways(); - el1.onTimer(); - el1.onFastTimer(); - - TDSC_ChannelState channelState; - el1.handleGetChannelState(channelState); - - EXPECT_EQ(el1.getChannelNumber(), -1); - EXPECT_EQ(el1.getChannel(), nullptr); - EXPECT_EQ(el1.getSecondaryChannel(), nullptr); - EXPECT_EQ(&(el1.disableChannelState()), &el1); - EXPECT_EQ(el1.next(), nullptr); - - EXPECT_EQ(el1.iterateConnected(nullptr), true); - EXPECT_EQ(el1.iterateConnected(&el1), true); - EXPECT_EQ(el1.handleNewValueFromServer(nullptr), -1); - EXPECT_EQ(el1.handleCalcfgFromServer(nullptr), SUPLA_CALCFG_RESULT_NOT_SUPPORTED); -} - -TEST_F(ElementTests, ChannelElementMethods) { - ElementWithChannel el1; - TimeInterfaceMock time; - SrpcMock srpc; - - EXPECT_CALL(time, millis()).Times(2); - - // those methods are empty, so just call to make sure that they do nothing and don't crash - el1.onInit(); - el1.onLoadState(); - el1.onSaveState(); - el1.onTimer(); - el1.onFastTimer(); - el1.onRegistered(); - - TDSC_ChannelState channelState; - el1.handleGetChannelState(channelState); - - EXPECT_EQ(el1.getChannelNumber(), 0); - EXPECT_EQ(el1.getChannel(), &(el1.channel)); - EXPECT_EQ(el1.getSecondaryChannel(), nullptr); - EXPECT_EQ(&(el1.disableChannelState()), &el1); - EXPECT_EQ(el1.next(), nullptr); - - EXPECT_FALSE(el1.channel.isUpdateReady()); - EXPECT_EQ(el1.iterateConnected(nullptr), true); - EXPECT_EQ(el1.iterateConnected(&el1), true); - EXPECT_EQ(el1.handleNewValueFromServer(nullptr), -1); - EXPECT_EQ(el1.handleCalcfgFromServer(nullptr), SUPLA_CALCFG_RESULT_NOT_SUPPORTED); - - EXPECT_FALSE(el1.channel.isUpdateReady()); - el1.channel.setNewValue(true); - EXPECT_TRUE(el1.channel.isUpdateReady()); - - EXPECT_CALL(time, millis) - .WillOnce(Return(0)) // #1 first call after value changed to true - .WillOnce(Return(200)) // #2 two calls after value changed to true and 100 ms passed - .WillOnce(Return(250)) // #3 value changed, however not enough time passed - .WillOnce(Return(250)) // #4 value changed, however not enough time passed - .WillOnce(Return(400)) // #5 two calls after value changed and another >100 ms passed - .WillOnce(Return(600)) - .WillOnce(Return(800)); - - char array0[SUPLA_CHANNELVALUE_SIZE] = {}; - char array1[SUPLA_CHANNELVALUE_SIZE] = {}; - array1[0] = 1; - EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array1), 0, 0)); // value at #2 - EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array0), 0, 0)); // value at #5 - EXPECT_CALL(srpc, getChannelConfig(0)); - - - EXPECT_EQ(el1.iterateConnected(nullptr), true); // #1 - EXPECT_EQ(el1.iterateConnected(nullptr), false); // #2 - - el1.channel.setNewValue(false); - EXPECT_EQ(el1.iterateConnected(nullptr), true); // #3 - EXPECT_EQ(el1.iterateConnected(nullptr), true); // #4 - EXPECT_EQ(el1.iterateConnected(nullptr), false); // #5 - - EXPECT_FALSE(el1.channel.isUpdateReady()); - el1.channel.requestChannelConfig(); - EXPECT_TRUE(el1.channel.isUpdateReady()); - EXPECT_EQ(el1.iterateConnected(nullptr), false); // #6 - EXPECT_EQ(el1.iterateConnected(nullptr), true); // #7 - -} - - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +using ::testing::Return; +using ::testing::ElementsAreArray; + +class ElementTests : public ::testing::Test { + protected: + virtual void SetUp() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + virtual void TearDown() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + +}; + + +class ElementWithChannel : public Supla::Element { + public: + Supla::Channel *getChannel() { + return &channel; + } + Supla::Channel channel; +}; + +TEST_F(ElementTests, ElementEmptyListTests) { + EXPECT_EQ(Supla::Element::begin(), nullptr); + EXPECT_EQ(Supla::Element::last(), nullptr); + EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); + EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), nullptr); + EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); +} + +TEST_F(ElementTests, ElementListAdding) { + auto el1 = new Supla::Element; + + EXPECT_EQ(Supla::Element::begin(), el1); + EXPECT_EQ(Supla::Element::last(), el1); + + EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); + // Element without channel number acts as channel with -1 number + EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), el1); + EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); + + auto el2 = new Supla::Element; + EXPECT_EQ(Supla::Element::begin(), el1); + EXPECT_EQ(Supla::Element::last(), el2); + + EXPECT_EQ(Supla::Element::getElementByChannelNumber(0), nullptr); + // Element without channel number acts as channel with -1 number + EXPECT_EQ(Supla::Element::getElementByChannelNumber(-1), el1); + EXPECT_EQ(Supla::Element::getElementByChannelNumber(10), nullptr); + + auto el3 = new Supla::Element; + EXPECT_EQ(Supla::Element::begin(), el1); + EXPECT_EQ(Supla::Element::last(), el3); + + delete el2; + + EXPECT_EQ(Supla::Element::begin(), el1); + EXPECT_EQ(Supla::Element::last(), el3); + + el2 = new Supla::Element; + EXPECT_EQ(Supla::Element::begin(), el1); + EXPECT_EQ(Supla::Element::last(), el2); + + delete el1; + EXPECT_EQ(Supla::Element::begin(), el3); + EXPECT_EQ(Supla::Element::last(), el2); + + el1 = new Supla::Element; + EXPECT_EQ(Supla::Element::begin(), el3); + EXPECT_EQ(Supla::Element::last(), el1); + + delete el1; + EXPECT_EQ(Supla::Element::begin(), el3); + EXPECT_EQ(Supla::Element::last(), el2); + + delete el2; + delete el3; + + EXPECT_EQ(Supla::Element::begin(), nullptr); + EXPECT_EQ(Supla::Element::last(), nullptr); + +} + +TEST_F(ElementTests, NoChannelElementMethods) { + TimeInterfaceMock time; + Supla::Element el1; + + EXPECT_CALL(time, millis()).Times(2); + + // those methods are empty, so just call to make sure that they do nothing and don't crash + el1.onInit(); + el1.onLoadState(); + el1.onSaveState(); + el1.iterateAlways(); + el1.onTimer(); + el1.onFastTimer(); + + TDSC_ChannelState channelState; + el1.handleGetChannelState(channelState); + + EXPECT_EQ(el1.getChannelNumber(), -1); + EXPECT_EQ(el1.getChannel(), nullptr); + EXPECT_EQ(el1.getSecondaryChannel(), nullptr); + EXPECT_EQ(&(el1.disableChannelState()), &el1); + EXPECT_EQ(el1.next(), nullptr); + + EXPECT_EQ(el1.iterateConnected(nullptr), true); + EXPECT_EQ(el1.iterateConnected(&el1), true); + EXPECT_EQ(el1.handleNewValueFromServer(nullptr), -1); + EXPECT_EQ(el1.handleCalcfgFromServer(nullptr), SUPLA_CALCFG_RESULT_NOT_SUPPORTED); +} + +TEST_F(ElementTests, ChannelElementMethods) { + ElementWithChannel el1; + TimeInterfaceMock time; + SrpcMock srpc; + + EXPECT_CALL(time, millis()).Times(2); + + // those methods are empty, so just call to make sure that they do nothing and don't crash + el1.onInit(); + el1.onLoadState(); + el1.onSaveState(); + el1.onTimer(); + el1.onFastTimer(); + el1.onRegistered(); + + TDSC_ChannelState channelState; + el1.handleGetChannelState(channelState); + + EXPECT_EQ(el1.getChannelNumber(), 0); + EXPECT_EQ(el1.getChannel(), &(el1.channel)); + EXPECT_EQ(el1.getSecondaryChannel(), nullptr); + EXPECT_EQ(&(el1.disableChannelState()), &el1); + EXPECT_EQ(el1.next(), nullptr); + + EXPECT_FALSE(el1.channel.isUpdateReady()); + EXPECT_EQ(el1.iterateConnected(nullptr), true); + EXPECT_EQ(el1.iterateConnected(&el1), true); + EXPECT_EQ(el1.handleNewValueFromServer(nullptr), -1); + EXPECT_EQ(el1.handleCalcfgFromServer(nullptr), SUPLA_CALCFG_RESULT_NOT_SUPPORTED); + + EXPECT_FALSE(el1.channel.isUpdateReady()); + el1.channel.setNewValue(true); + EXPECT_TRUE(el1.channel.isUpdateReady()); + + EXPECT_CALL(time, millis) + .WillOnce(Return(0)) // #1 first call after value changed to true + .WillOnce(Return(200)) // #2 two calls after value changed to true and 100 ms passed + .WillOnce(Return(250)) // #3 value changed, however not enough time passed + .WillOnce(Return(250)) // #4 value changed, however not enough time passed + .WillOnce(Return(400)) // #5 two calls after value changed and another >100 ms passed + .WillOnce(Return(600)) + .WillOnce(Return(800)); + + char array0[SUPLA_CHANNELVALUE_SIZE] = {}; + char array1[SUPLA_CHANNELVALUE_SIZE] = {}; + array1[0] = 1; + EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array1), 0, 0)); // value at #2 + EXPECT_CALL(srpc, valueChanged(nullptr, 0, ElementsAreArray(array0), 0, 0)); // value at #5 + EXPECT_CALL(srpc, getChannelConfig(0)); + + + EXPECT_EQ(el1.iterateConnected(nullptr), true); // #1 + EXPECT_EQ(el1.iterateConnected(nullptr), false); // #2 + + el1.channel.setNewValue(false); + EXPECT_EQ(el1.iterateConnected(nullptr), true); // #3 + EXPECT_EQ(el1.iterateConnected(nullptr), true); // #4 + EXPECT_EQ(el1.iterateConnected(nullptr), false); // #5 + + EXPECT_FALSE(el1.channel.isUpdateReady()); + el1.channel.requestChannelConfig(); + EXPECT_TRUE(el1.channel.isUpdateReady()); + EXPECT_EQ(el1.iterateConnected(nullptr), false); // #6 + EXPECT_EQ(el1.iterateConnected(nullptr), true); // #7 + +} + + + diff --git a/lib/SuplaDevice/extras/test/LocalActionTests/local_action_tests.cpp b/lib/SuplaDevice/extras/test/LocalActionTests/local_action_tests.cpp index 27785418..19fd2aae 100644 --- a/lib/SuplaDevice/extras/test/LocalActionTests/local_action_tests.cpp +++ b/lib/SuplaDevice/extras/test/LocalActionTests/local_action_tests.cpp @@ -1,183 +1,183 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include - -class ActionHandlerMock : public Supla::ActionHandler { - public: - MOCK_METHOD(void, handleAction, (int, int), (override)); -}; - -TEST(LocalActionTests, TwoItemsTests) { - auto b1 = new Supla::LocalAction; - auto b2 = new Supla::LocalAction; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - - int action1 = 1; - int action2 = 2; - int action3 = 3; - int action4 = 4; - int action5 = 5; - int event1 = 11; - int event2 = 12; - int event3 = 13; - - EXPECT_CALL(mock1, handleAction(event1, action1)); - EXPECT_CALL(mock1, handleAction(event1, action3)); - EXPECT_CALL(mock2, handleAction(event3, action1)); - EXPECT_CALL(mock1, handleAction(event2, action2)); - EXPECT_CALL(mock1, handleAction(event2, action4)); - EXPECT_CALL(mock1, handleAction(event2, action5)); - EXPECT_CALL(mock2, handleAction(event1, action1)); - EXPECT_CALL(mock2, handleAction(event2, action2)); - - b1->addAction(action1, mock1, event1); - b1->addAction(action2, mock1, event2); - b1->addAction(action3, mock1, event1); - b1->addAction(action4, mock1, event2); - b1->addAction(action5, mock1, event2); - b1->addAction(action1, mock2, event3); - b2->addAction(action1, mock2, event1); - b2->addAction(action2, mock2, event2); - b1->runAction(event1); - b1->runAction(event3); - b1->runAction(event2); - - b2->runAction(event1); - - EXPECT_TRUE(b1->isEventAlreadyUsed(event1)); - EXPECT_TRUE(b2->isEventAlreadyUsed(event2)); - - EXPECT_FALSE(b1->isEventAlreadyUsed(432)); - EXPECT_FALSE(b2->isEventAlreadyUsed(event3)); - - delete b1; - - b2->runAction(event2); - - delete b2; -} - -TEST(LocalActionTests, FourItemsTestsNoCalls) { - auto b1 = new Supla::LocalAction; - auto b2 = new Supla::LocalAction; - auto b3 = new Supla::LocalAction; - auto b4 = new Supla::LocalAction; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - ActionHandlerMock mock3; - ActionHandlerMock mock4; - - EXPECT_CALL(mock1, handleAction).Times(0); - EXPECT_CALL(mock2, handleAction).Times(0); - EXPECT_CALL(mock3, handleAction).Times(0); - EXPECT_CALL(mock4, handleAction).Times(0); - - int action1 = 1; - int action2 = 2; - int action3 = 3; - int action4 = 4; - int action5 = 5; - int event1 = 11; - int event2 = 12; - int event3 = 13; - int event4 = 14; - - b4->addAction(action4, mock4, event4); - b3->addAction(action3, mock3, event3); - b1->addAction(action1, mock1, event1); - b2->addAction(action2, mock2, event2); - - b1->runAction(event2); - b1->runAction(event3); - b1->runAction(event4); - - b2->runAction(event1); - b2->runAction(event3); - b2->runAction(event4); - - b3->runAction(event1); - b3->runAction(event2); - b3->runAction(event4); - - b4->runAction(event1); - b4->runAction(event2); - b4->runAction(event3); - - delete b1; - delete b2; - delete b3; - delete b4; -} - -TEST(LocalActionTests, FourItemsTestsWithCalls) { - auto b1 = new Supla::LocalAction; - auto b2 = new Supla::LocalAction; - auto b3 = new Supla::LocalAction; - auto b4 = new Supla::LocalAction; - ActionHandlerMock mock1; - ActionHandlerMock mock2; - ActionHandlerMock mock3; - ActionHandlerMock mock4; - - int action1 = 1; - int action2 = 2; - int action3 = 3; - int action4 = 4; - int action5 = 5; - int event1 = 11; - int event2 = 12; - int event3 = 13; - int event4 = 14; - - EXPECT_CALL(mock1, handleAction(event1, action1)); - EXPECT_CALL(mock2, handleAction(event2, action2)); - EXPECT_CALL(mock3, handleAction(event3, action3)); - EXPECT_CALL(mock4, handleAction(event4, action4)); - - b4->addAction(action4, mock4, event4); - b3->addAction(action3, mock3, event3); - b1->addAction(action1, mock1, event1); - b2->addAction(action2, mock2, event2); - - b1->runAction(event1); - b1->runAction(event2); - b1->runAction(event3); - b1->runAction(event4); - - b2->runAction(event1); - b2->runAction(event2); - b2->runAction(event3); - b2->runAction(event4); - - b3->runAction(event3); - b3->runAction(event1); - b3->runAction(event2); - b3->runAction(event4); - - b4->runAction(event1); - b4->runAction(event2); - b4->runAction(event3); - b4->runAction(event4); - - delete b1; - delete b2; - delete b3; - delete b4; -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include + +class ActionHandlerMock : public Supla::ActionHandler { + public: + MOCK_METHOD(void, handleAction, (int, int), (override)); +}; + +TEST(LocalActionTests, TwoItemsTests) { + auto b1 = new Supla::LocalAction; + auto b2 = new Supla::LocalAction; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + + int action1 = 1; + int action2 = 2; + int action3 = 3; + int action4 = 4; + int action5 = 5; + int event1 = 11; + int event2 = 12; + int event3 = 13; + + EXPECT_CALL(mock1, handleAction(event1, action1)); + EXPECT_CALL(mock1, handleAction(event1, action3)); + EXPECT_CALL(mock2, handleAction(event3, action1)); + EXPECT_CALL(mock1, handleAction(event2, action2)); + EXPECT_CALL(mock1, handleAction(event2, action4)); + EXPECT_CALL(mock1, handleAction(event2, action5)); + EXPECT_CALL(mock2, handleAction(event1, action1)); + EXPECT_CALL(mock2, handleAction(event2, action2)); + + b1->addAction(action1, mock1, event1); + b1->addAction(action2, mock1, event2); + b1->addAction(action3, mock1, event1); + b1->addAction(action4, mock1, event2); + b1->addAction(action5, mock1, event2); + b1->addAction(action1, mock2, event3); + b2->addAction(action1, mock2, event1); + b2->addAction(action2, mock2, event2); + b1->runAction(event1); + b1->runAction(event3); + b1->runAction(event2); + + b2->runAction(event1); + + EXPECT_TRUE(b1->isEventAlreadyUsed(event1)); + EXPECT_TRUE(b2->isEventAlreadyUsed(event2)); + + EXPECT_FALSE(b1->isEventAlreadyUsed(432)); + EXPECT_FALSE(b2->isEventAlreadyUsed(event3)); + + delete b1; + + b2->runAction(event2); + + delete b2; +} + +TEST(LocalActionTests, FourItemsTestsNoCalls) { + auto b1 = new Supla::LocalAction; + auto b2 = new Supla::LocalAction; + auto b3 = new Supla::LocalAction; + auto b4 = new Supla::LocalAction; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + ActionHandlerMock mock3; + ActionHandlerMock mock4; + + EXPECT_CALL(mock1, handleAction).Times(0); + EXPECT_CALL(mock2, handleAction).Times(0); + EXPECT_CALL(mock3, handleAction).Times(0); + EXPECT_CALL(mock4, handleAction).Times(0); + + int action1 = 1; + int action2 = 2; + int action3 = 3; + int action4 = 4; + int action5 = 5; + int event1 = 11; + int event2 = 12; + int event3 = 13; + int event4 = 14; + + b4->addAction(action4, mock4, event4); + b3->addAction(action3, mock3, event3); + b1->addAction(action1, mock1, event1); + b2->addAction(action2, mock2, event2); + + b1->runAction(event2); + b1->runAction(event3); + b1->runAction(event4); + + b2->runAction(event1); + b2->runAction(event3); + b2->runAction(event4); + + b3->runAction(event1); + b3->runAction(event2); + b3->runAction(event4); + + b4->runAction(event1); + b4->runAction(event2); + b4->runAction(event3); + + delete b1; + delete b2; + delete b3; + delete b4; +} + +TEST(LocalActionTests, FourItemsTestsWithCalls) { + auto b1 = new Supla::LocalAction; + auto b2 = new Supla::LocalAction; + auto b3 = new Supla::LocalAction; + auto b4 = new Supla::LocalAction; + ActionHandlerMock mock1; + ActionHandlerMock mock2; + ActionHandlerMock mock3; + ActionHandlerMock mock4; + + int action1 = 1; + int action2 = 2; + int action3 = 3; + int action4 = 4; + int action5 = 5; + int event1 = 11; + int event2 = 12; + int event3 = 13; + int event4 = 14; + + EXPECT_CALL(mock1, handleAction(event1, action1)); + EXPECT_CALL(mock2, handleAction(event2, action2)); + EXPECT_CALL(mock3, handleAction(event3, action3)); + EXPECT_CALL(mock4, handleAction(event4, action4)); + + b4->addAction(action4, mock4, event4); + b3->addAction(action3, mock3, event3); + b1->addAction(action1, mock1, event1); + b2->addAction(action2, mock2, event2); + + b1->runAction(event1); + b1->runAction(event2); + b1->runAction(event3); + b1->runAction(event4); + + b2->runAction(event1); + b2->runAction(event2); + b2->runAction(event3); + b2->runAction(event4); + + b3->runAction(event3); + b3->runAction(event1); + b3->runAction(event2); + b3->runAction(event4); + + b4->runAction(event1); + b4->runAction(event2); + b4->runAction(event3); + b4->runAction(event4); + + delete b1; + delete b2; + delete b3; + delete b4; +} diff --git a/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_full_startup_tests.cpp b/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_full_startup_tests.cpp index 95413c70..e4d88c46 100644 --- a/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_full_startup_tests.cpp +++ b/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_full_startup_tests.cpp @@ -1,223 +1,223 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using ::testing::Return; -using ::testing::_; -using ::testing::DoAll; -using ::testing::Assign; -using ::testing::ReturnPointee; - -class SuplaDeviceTests : public ::testing::Test { - protected: - virtual void SetUp() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - virtual void TearDown() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - -}; - -class TimeInterfaceStub : public TimeInterface { - public: - virtual unsigned long millis() override { - static unsigned long value = 0; - value += 1000; - return value; - } -}; - -class StorageMock2: public Supla::Storage { - public: - MOCK_METHOD(bool, init, (), (override)); - MOCK_METHOD(bool, prepareState, (bool), (override)); - MOCK_METHOD(bool, finalizeSaveState, (), (override)); - MOCK_METHOD(void, commit, (), (override)); - MOCK_METHOD(int, readStorage, (unsigned int, unsigned char *, int, bool), (override)); - MOCK_METHOD(int, writeStorage, (unsigned int, const unsigned char *, int), (override)); - -}; - -class NetworkMock : public Supla::Network { - public: - NetworkMock() : Supla::Network(nullptr) {}; - MOCK_METHOD(int, read, (void *, int ), (override)); - MOCK_METHOD(int, write, (void *, int ), (override)); - MOCK_METHOD(int, connect, (const char *, int), (override)); - MOCK_METHOD(bool, connected, (), (override)); - MOCK_METHOD(void, disconnect, (), (override)); - MOCK_METHOD(void, setup, (), (override)); - MOCK_METHOD(void, setTimeout, (int), (override)); - - MOCK_METHOD(bool, isReady, (), (override)); - MOCK_METHOD(bool, iterate, (), (override)); - MOCK_METHOD(bool, ping, (void *), (override)); - -}; - -class SuplaDeviceTestsFullStartup : public SuplaDeviceTests { - protected: - SrpcMock srpc; - NetworkMock net; - TimerMock timer; - TimeInterfaceStub time; - SuplaDeviceClass sd; - ElementMock el1; - ElementMock el2; - - virtual void SetUp() { - SuplaDeviceTests::SetUp(); - - int dummy; - - EXPECT_CALL(el1, onInit()); - EXPECT_CALL(el2, onInit()); - - EXPECT_CALL(timer, initTimers()); - EXPECT_CALL(net, setup()); - EXPECT_CALL(srpc, srpc_params_init(_)); - EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); - EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; - EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); - } - - virtual void TearDown() { - SuplaDeviceTests::TearDown(); - } -}; - -using ::testing::AtLeast; - -TEST_F(SuplaDeviceTestsFullStartup, NoNetworkShouldCallSetupAgain) { - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(false)); - EXPECT_CALL(net, setup()).Times(2); - EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); - EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); - - for (int i = 0; i < 50*30; i++) sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_NETWORK_DISCONNECTED); -} - -TEST_F(SuplaDeviceTestsFullStartup, FailedConnectionShouldSetupNetworkAgain) { - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(net, connected()).WillRepeatedly(Return(false)); - EXPECT_CALL(net, connect(_, _)).WillRepeatedly(Return(0)); - EXPECT_CALL(net, disconnect()).Times(AtLeast(1)); - - EXPECT_CALL(net, setup()).Times(1); - EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); - EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); - - for (int i = 0; i < 2*31; i++) sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_SERVER_DISCONNECTED); -} - -TEST_F(SuplaDeviceTestsFullStartup, SrpcFailureShouldCallDisconnect) { - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(net, connected()).WillOnce(Return(false)).WillRepeatedly(Return(false)); - EXPECT_CALL(net, connect(_, _)).WillRepeatedly(Return(1)); - EXPECT_CALL(net, iterate()).Times(1); - EXPECT_CALL(srpc, srpc_iterate(_)).WillOnce(Return(SUPLA_RESULT_FALSE)); - - EXPECT_CALL(net, disconnect()).Times(1); - - EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); - EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); - - sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_ITERATE_FAIL); -} - -TEST_F(SuplaDeviceTestsFullStartup, NoReplyForDeviceRegistrationShoudResetConnection) { - bool isConnected = false; - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(net, connected()).WillRepeatedly(ReturnPointee(&isConnected)); - EXPECT_CALL(net, connect(_, _)).WillRepeatedly(DoAll(Assign(&isConnected, true), Return(1))); - - EXPECT_CALL(net, iterate()).Times(AtLeast(1)); - EXPECT_CALL(srpc, srpc_iterate(_)).WillRepeatedly(Return(SUPLA_RESULT_TRUE)); - - EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); - EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); - - EXPECT_CALL(net, disconnect()).WillOnce(Assign(&isConnected, false)); - - EXPECT_CALL(srpc, srpc_ds_async_registerdevice_e(_, _)).Times(2); - - for (int i = 0; i < 11; i++) sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_SERVER_DISCONNECTED); - for (int i = 0; i < 2; i++) sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTER_IN_PROGRESS); -} - - -TEST_F(SuplaDeviceTestsFullStartup, SuccessfulStartup) { - bool isConnected = false; - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); - EXPECT_CALL(net, connected()).WillRepeatedly(ReturnPointee(&isConnected)); - EXPECT_CALL(net, connect(_, _)).WillRepeatedly(DoAll(Assign(&isConnected, true), Return(1))); - - EXPECT_CALL(net, iterate()).Times(AtLeast(1)); - EXPECT_CALL(srpc, srpc_iterate(_)).WillRepeatedly(Return(SUPLA_RESULT_TRUE)); - - EXPECT_CALL(el1, iterateAlways()).Times(35); - EXPECT_CALL(el2, iterateAlways()).Times(35); - - EXPECT_CALL(el1, onRegistered()); - EXPECT_CALL(el2, onRegistered()); - - EXPECT_CALL(srpc, srpc_ds_async_registerdevice_e(_, _)).Times(1); - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(1); - - EXPECT_CALL(net, ping(_)).WillRepeatedly(Return(true)); - EXPECT_CALL(el1, iterateConnected(_)).Times(30).WillRepeatedly(Return(true)); - EXPECT_CALL(el2, iterateConnected(_)).Times(30).WillRepeatedly(Return(true)); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); - for (int i = 0; i < 5; i++) sd.iterate(); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTER_IN_PROGRESS); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_TRUE; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); - - for (int i = 0; i < 30; i++) sd.iterate(); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::testing::Return; +using ::testing::_; +using ::testing::DoAll; +using ::testing::Assign; +using ::testing::ReturnPointee; + +class SuplaDeviceTests : public ::testing::Test { + protected: + virtual void SetUp() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + virtual void TearDown() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + +}; + +class TimeInterfaceStub : public TimeInterface { + public: + virtual unsigned long millis() override { + static unsigned long value = 0; + value += 1000; + return value; + } +}; + +class StorageMock2: public Supla::Storage { + public: + MOCK_METHOD(bool, init, (), (override)); + MOCK_METHOD(bool, prepareState, (bool), (override)); + MOCK_METHOD(bool, finalizeSaveState, (), (override)); + MOCK_METHOD(void, commit, (), (override)); + MOCK_METHOD(int, readStorage, (unsigned int, unsigned char *, int, bool), (override)); + MOCK_METHOD(int, writeStorage, (unsigned int, const unsigned char *, int), (override)); + +}; + +class NetworkMock : public Supla::Network { + public: + NetworkMock() : Supla::Network(nullptr) {}; + MOCK_METHOD(int, read, (void *, int ), (override)); + MOCK_METHOD(int, write, (void *, int ), (override)); + MOCK_METHOD(int, connect, (const char *, int), (override)); + MOCK_METHOD(bool, connected, (), (override)); + MOCK_METHOD(void, disconnect, (), (override)); + MOCK_METHOD(void, setup, (), (override)); + MOCK_METHOD(void, setTimeout, (int), (override)); + + MOCK_METHOD(bool, isReady, (), (override)); + MOCK_METHOD(bool, iterate, (), (override)); + MOCK_METHOD(bool, ping, (void *), (override)); + +}; + +class SuplaDeviceTestsFullStartup : public SuplaDeviceTests { + protected: + SrpcMock srpc; + NetworkMock net; + TimerMock timer; + TimeInterfaceStub time; + SuplaDeviceClass sd; + ElementMock el1; + ElementMock el2; + + virtual void SetUp() { + SuplaDeviceTests::SetUp(); + + int dummy; + + EXPECT_CALL(el1, onInit()); + EXPECT_CALL(el2, onInit()); + + EXPECT_CALL(timer, initTimers()); + EXPECT_CALL(net, setup()); + EXPECT_CALL(srpc, srpc_params_init(_)); + EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); + EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; + EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); + } + + virtual void TearDown() { + SuplaDeviceTests::TearDown(); + } +}; + +using ::testing::AtLeast; + +TEST_F(SuplaDeviceTestsFullStartup, NoNetworkShouldCallSetupAgain) { + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(false)); + EXPECT_CALL(net, setup()).Times(2); + EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); + EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); + + for (int i = 0; i < 50*30; i++) sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_NETWORK_DISCONNECTED); +} + +TEST_F(SuplaDeviceTestsFullStartup, FailedConnectionShouldSetupNetworkAgain) { + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); + EXPECT_CALL(net, connected()).WillRepeatedly(Return(false)); + EXPECT_CALL(net, connect(_, _)).WillRepeatedly(Return(0)); + EXPECT_CALL(net, disconnect()).Times(AtLeast(1)); + + EXPECT_CALL(net, setup()).Times(1); + EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); + EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); + + for (int i = 0; i < 2*31; i++) sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_SERVER_DISCONNECTED); +} + +TEST_F(SuplaDeviceTestsFullStartup, SrpcFailureShouldCallDisconnect) { + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); + EXPECT_CALL(net, connected()).WillOnce(Return(false)).WillRepeatedly(Return(false)); + EXPECT_CALL(net, connect(_, _)).WillRepeatedly(Return(1)); + EXPECT_CALL(net, iterate()).Times(1); + EXPECT_CALL(srpc, srpc_iterate(_)).WillOnce(Return(SUPLA_RESULT_FALSE)); + + EXPECT_CALL(net, disconnect()).Times(1); + + EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); + EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); + + sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_ITERATE_FAIL); +} + +TEST_F(SuplaDeviceTestsFullStartup, NoReplyForDeviceRegistrationShoudResetConnection) { + bool isConnected = false; + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); + EXPECT_CALL(net, connected()).WillRepeatedly(ReturnPointee(&isConnected)); + EXPECT_CALL(net, connect(_, _)).WillRepeatedly(DoAll(Assign(&isConnected, true), Return(1))); + + EXPECT_CALL(net, iterate()).Times(AtLeast(1)); + EXPECT_CALL(srpc, srpc_iterate(_)).WillRepeatedly(Return(SUPLA_RESULT_TRUE)); + + EXPECT_CALL(el1, iterateAlways()).Times(AtLeast(1)); + EXPECT_CALL(el2, iterateAlways()).Times(AtLeast(1)); + + EXPECT_CALL(net, disconnect()).WillOnce(Assign(&isConnected, false)); + + EXPECT_CALL(srpc, srpc_ds_async_registerdevice_e(_, _)).Times(2); + + for (int i = 0; i < 11; i++) sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_SERVER_DISCONNECTED); + for (int i = 0; i < 2; i++) sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTER_IN_PROGRESS); +} + + +TEST_F(SuplaDeviceTestsFullStartup, SuccessfulStartup) { + bool isConnected = false; + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(true)); + EXPECT_CALL(net, connected()).WillRepeatedly(ReturnPointee(&isConnected)); + EXPECT_CALL(net, connect(_, _)).WillRepeatedly(DoAll(Assign(&isConnected, true), Return(1))); + + EXPECT_CALL(net, iterate()).Times(AtLeast(1)); + EXPECT_CALL(srpc, srpc_iterate(_)).WillRepeatedly(Return(SUPLA_RESULT_TRUE)); + + EXPECT_CALL(el1, iterateAlways()).Times(35); + EXPECT_CALL(el2, iterateAlways()).Times(35); + + EXPECT_CALL(el1, onRegistered()); + EXPECT_CALL(el2, onRegistered()); + + EXPECT_CALL(srpc, srpc_ds_async_registerdevice_e(_, _)).Times(1); + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(1); + + EXPECT_CALL(net, ping(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(el1, iterateConnected(_)).Times(30).WillRepeatedly(Return(true)); + EXPECT_CALL(el2, iterateConnected(_)).Times(30).WillRepeatedly(Return(true)); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); + for (int i = 0; i < 5; i++) sd.iterate(); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTER_IN_PROGRESS); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_TRUE; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); + + for (int i = 0; i < 30; i++) sd.iterate(); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); +} + diff --git a/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_tests.cpp b/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_tests.cpp index 7a0f3d6d..5b33ac8d 100644 --- a/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_tests.cpp +++ b/lib/SuplaDevice/extras/test/SuplaDeviceTests/supla_device_tests.cpp @@ -1,657 +1,657 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using ::testing::Return; -using ::testing::_; -using ::testing::DoAll; -using ::testing::Assign; -using ::testing::ReturnPointee; - -class SuplaDeviceTests : public ::testing::Test { - protected: - virtual void SetUp() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - virtual void TearDown() { - Supla::Channel::lastCommunicationTimeMs = 0; - memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); - } - -}; - -class TimeInterfaceStub : public TimeInterface { - public: - virtual unsigned long millis() override { - static unsigned long value = 0; - value += 1000; - return value; - } -}; - -TEST_F(SuplaDeviceTests, DefaultValuesTest) { - SuplaDeviceClass sd; - SrpcMock srpc; - TimerMock timer; - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN); - EXPECT_EQ(sd.getClock(), nullptr); -} - -class ClockMock : public Supla::Clock { - public: - MOCK_METHOD(void, parseLocaltimeFromServer, (TSDC_UserLocalTimeResult *result), (override)); -}; - -TEST_F(SuplaDeviceTests, ClockMethods) { - SuplaDeviceClass sd; - ClockMock clock; - - ASSERT_EQ(sd.getClock(), nullptr); - sd.onGetUserLocaltimeResult(nullptr); - - sd.addClock(&clock); - ASSERT_EQ(sd.getClock(), &clock); - - EXPECT_CALL(clock, parseLocaltimeFromServer(nullptr)).Times(1); - - sd.onGetUserLocaltimeResult(nullptr); -} - -TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElements) { - SuplaDeviceClass sd; - TimerMock timer; - - ASSERT_EQ(Supla::Element::begin(), nullptr); - EXPECT_CALL(timer, initTimers()); - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); -} - -class StorageMock2: public Supla::Storage { - public: - MOCK_METHOD(bool, init, (), (override)); - MOCK_METHOD(bool, prepareState, (bool), (override)); - MOCK_METHOD(bool, finalizeSaveState, (), (override)); - MOCK_METHOD(void, commit, (), (override)); - MOCK_METHOD(int, readStorage, (unsigned int, unsigned char *, int, bool), (override)); - MOCK_METHOD(int, writeStorage, (unsigned int, const unsigned char *, int), (override)); - -}; - -TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElementsWithStorage) { - ::testing::InSequence seq; - SuplaDeviceClass sd; - TimerMock timer; - StorageMock2 storage; - - ASSERT_EQ(Supla::Element::begin(), nullptr); - EXPECT_CALL(storage, init()); - EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true));; - EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(false)); - - EXPECT_CALL(timer, initTimers()); - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); -} - -TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElementsWithStorageAndDataLoadAttempt) { - ::testing::InSequence seq; - SuplaDeviceClass sd; - TimerMock timer; - StorageMock2 storage; - - ASSERT_EQ(Supla::Element::begin(), nullptr); - EXPECT_CALL(storage, init()); - EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); - EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); - EXPECT_CALL(storage, prepareState(false)); - - EXPECT_CALL(timer, initTimers()); - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); -} - -TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceWithElements) { - ::testing::InSequence seq; - SuplaDeviceClass sd; - TimerMock timer; - ElementMock el1; - ElementMock el2; - - ASSERT_NE(Supla::Element::begin(), nullptr); - - EXPECT_CALL(el1, onInit()); - EXPECT_CALL(el2, onInit()); - - EXPECT_CALL(timer, initTimers()); - EXPECT_CALL(el1, onTimer()); - EXPECT_CALL(el2, onTimer()); - EXPECT_CALL(el1, onFastTimer()); - EXPECT_CALL(el2, onFastTimer()); - - - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); - sd.onTimer(); - sd.onFastTimer(); -} - -TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceWithElementsWithStorage) { - ::testing::InSequence seq; - StorageMock2 storage; - SuplaDeviceClass sd; - TimerMock timer; - ElementMock el1; - ElementMock el2; - - ASSERT_NE(Supla::Element::begin(), nullptr); - - EXPECT_CALL(storage, init()); - EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); - EXPECT_CALL(el1, onSaveState()); - EXPECT_CALL(el2, onSaveState()); - - EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); - EXPECT_CALL(storage, prepareState(false)); - EXPECT_CALL(el1, onLoadState()); - EXPECT_CALL(el2, onLoadState()); - - EXPECT_CALL(el1, onInit()); - EXPECT_CALL(el2, onInit()); - - EXPECT_CALL(timer, initTimers()); - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); -} - -class NetworkMock : public Supla::Network { - public: - NetworkMock() : Supla::Network(nullptr) {}; - MOCK_METHOD(int, read, (void *, int ), (override)); - MOCK_METHOD(int, write, (void *, int ), (override)); - MOCK_METHOD(int, connect, (const char *, int), (override)); - MOCK_METHOD(bool, connected, (), (override)); - MOCK_METHOD(void, disconnect, (), (override)); - MOCK_METHOD(void, setup, (), (override)); - MOCK_METHOD(void, setTimeout, (int), (override)); - - MOCK_METHOD(bool, isReady, (), (override)); - MOCK_METHOD(bool, iterate, (), (override)); - MOCK_METHOD(bool, ping, (void *), (override)); - -}; - -TEST_F(SuplaDeviceTests, BeginStopsAtEmptyGUID) { - ::testing::InSequence seq; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - - EXPECT_CALL(timer, initTimers()); - - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_GUID); -} - -TEST_F(SuplaDeviceTests, BeginStopsAtEmptyServer) { - ::testing::InSequence seq; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - - EXPECT_CALL(timer, initTimers()); - - char GUID[SUPLA_GUID_SIZE] = {1}; - sd.setGUID(GUID); - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN_SERVER_ADDRESS); -} - -TEST_F(SuplaDeviceTests, BeginStopsAtEmptyEmail) { - ::testing::InSequence seq; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - - EXPECT_CALL(timer, initTimers()); - - char GUID[SUPLA_GUID_SIZE] = {1}; - sd.setGUID(GUID); - sd.setServer("supla.rulez"); - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_CREDENTIALS); -} - - -TEST_F(SuplaDeviceTests, BeginStopsAtEmptyAuthkey) { - ::testing::InSequence seq; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - - EXPECT_CALL(timer, initTimers()); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; - sd.setGUID(GUID); - sd.setServer("supla.rulez"); - sd.setEmail("john@supla"); - EXPECT_FALSE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); -} - -TEST_F(SuplaDeviceTests, SuccessfulBegin) { - ::testing::InSequence seq; - SrpcMock srpc; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - int dummy; - - EXPECT_CALL(timer, initTimers()); - EXPECT_CALL(net, setup()); - EXPECT_CALL(srpc, srpc_params_init(_)); - EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); - EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; - sd.setGUID(GUID); - sd.setServer("supla.rulez"); - sd.setEmail("john@supla"); - sd.setAuthKey(AUTHKEY); - EXPECT_TRUE(sd.begin()); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); -} - - - -TEST_F(SuplaDeviceTests, SuccessfulBeginAlternative) { - ::testing::InSequence seq; - SrpcMock srpc; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - int dummy; - - EXPECT_CALL(timer, initTimers()); - EXPECT_CALL(net, setup()); - EXPECT_CALL(srpc, srpc_params_init(_)); - EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); - EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; - EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); -} - - -TEST_F(SuplaDeviceTests, FailedBeginAlternativeOnEmptyAUTHKEY) { - ::testing::InSequence seq; - SrpcMock srpc; - NetworkMock net; - TimerMock timer; - - SuplaDeviceClass sd; - int dummy; - - EXPECT_CALL(timer, initTimers()); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0}; - EXPECT_FALSE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); -} - -TEST_F(SuplaDeviceTests, TwoChannelElementsNoNetworkWithStorage) { - SrpcMock srpc; - NetworkMock net; - StorageMock2 storage; - TimerMock timer; - TimeInterfaceStub time; - SuplaDeviceClass sd; - ElementMock el1; - ElementMock el2; - int dummy; - EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); - EXPECT_CALL(storage, init()); - EXPECT_CALL(el1, onSaveState()); - EXPECT_CALL(el2, onSaveState()); - - EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); - EXPECT_CALL(storage, prepareState(false)); - EXPECT_CALL(el1, onLoadState()); - EXPECT_CALL(el2, onLoadState()); - - EXPECT_CALL(el1, onInit()); - EXPECT_CALL(el2, onInit()); - - EXPECT_CALL(timer, initTimers()); - EXPECT_CALL(net, setup()); - EXPECT_CALL(srpc, srpc_params_init(_)); - EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); - EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); - - char GUID[SUPLA_GUID_SIZE] = {1}; - char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; - EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); - EXPECT_CALL(el1, iterateAlways()).Times(2); - EXPECT_CALL(el2, iterateAlways()).Times(2); - EXPECT_CALL(net, isReady()).WillRepeatedly(Return(false)); - - EXPECT_CALL(storage, prepareState(false)); - EXPECT_CALL(el1, onSaveState()); - EXPECT_CALL(el2, onSaveState()); - EXPECT_CALL(storage, finalizeSaveState()); - - for (int i = 0; i < 2; i++) sd.iterate(); -} - -TEST_F(SuplaDeviceTests, OnVersionErrorShouldCallDisconnect) { - NetworkMock net; - TimeInterfaceStub time; - - EXPECT_CALL(net, disconnect()).Times(1); - - SuplaDeviceClass sd; - TSDC_SuplaVersionError versionError{}; - - sd.onVersionError(&versionError); - EXPECT_EQ(sd.getCurrentStatus(), STATUS_PROTOCOL_VERSION_ERROR); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultOK) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_TRUE; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultBadCredentials) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_BAD_CREDENTIALS; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_BAD_CREDENTIALS); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultTemporairlyUnavailable) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_TEMPORARILY_UNAVAILABLE); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultLocationConflict) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_LOCATION_CONFLICT; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_LOCATION_CONFLICT); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultChannelConflict) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_CHANNEL_CONFLICT; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_CHANNEL_CONFLICT); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultDeviceDisabled) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_DEVICE_DISABLED; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_DEVICE_IS_DISABLED); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultLocationDisabled) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_LOCATION_DISABLED; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_LOCATION_IS_DISABLED); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultDeviceLimitExceeded) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_DEVICE_LIMIT_EXCEEDED); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultGuidError) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_GUID_ERROR; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_GUID); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultAuthKeyError) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_AUTHKEY_ERROR; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultRegistrationDisabled) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_REGISTRATION_DISABLED; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTRATION_DISABLED); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultNoLocationAvailable) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_NO_LOCATION_AVAILABLE); -} - -TEST_F(SuplaDeviceTests, OnRegisterResultUnknownError) { - NetworkMock net; - SrpcMock srpc; - TimeInterfaceStub time; - SuplaDeviceClass sd; - - EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); - EXPECT_CALL(net, disconnect()).Times(1); - - TSD_SuplaRegisterDeviceResult register_device_result{}; - register_device_result.result_code = 666; - register_device_result.activity_timeout = 45; - register_device_result.version = 16; - register_device_result.version_min = 1; - - sd.onRegisterResult(®ister_device_result); - - EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN_ERROR); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::testing::Return; +using ::testing::_; +using ::testing::DoAll; +using ::testing::Assign; +using ::testing::ReturnPointee; + +class SuplaDeviceTests : public ::testing::Test { + protected: + virtual void SetUp() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + virtual void TearDown() { + Supla::Channel::lastCommunicationTimeMs = 0; + memset(&(Supla::Channel::reg_dev), 0, sizeof(Supla::Channel::reg_dev)); + } + +}; + +class TimeInterfaceStub : public TimeInterface { + public: + virtual unsigned long millis() override { + static unsigned long value = 0; + value += 1000; + return value; + } +}; + +TEST_F(SuplaDeviceTests, DefaultValuesTest) { + SuplaDeviceClass sd; + SrpcMock srpc; + TimerMock timer; + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN); + EXPECT_EQ(sd.getClock(), nullptr); +} + +class ClockMock : public Supla::Clock { + public: + MOCK_METHOD(void, parseLocaltimeFromServer, (TSDC_UserLocalTimeResult *result), (override)); +}; + +TEST_F(SuplaDeviceTests, ClockMethods) { + SuplaDeviceClass sd; + ClockMock clock; + + ASSERT_EQ(sd.getClock(), nullptr); + sd.onGetUserLocaltimeResult(nullptr); + + sd.addClock(&clock); + ASSERT_EQ(sd.getClock(), &clock); + + EXPECT_CALL(clock, parseLocaltimeFromServer(nullptr)).Times(1); + + sd.onGetUserLocaltimeResult(nullptr); +} + +TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElements) { + SuplaDeviceClass sd; + TimerMock timer; + + ASSERT_EQ(Supla::Element::begin(), nullptr); + EXPECT_CALL(timer, initTimers()); + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); +} + +class StorageMock2: public Supla::Storage { + public: + MOCK_METHOD(bool, init, (), (override)); + MOCK_METHOD(bool, prepareState, (bool), (override)); + MOCK_METHOD(bool, finalizeSaveState, (), (override)); + MOCK_METHOD(void, commit, (), (override)); + MOCK_METHOD(int, readStorage, (unsigned int, unsigned char *, int, bool), (override)); + MOCK_METHOD(int, writeStorage, (unsigned int, const unsigned char *, int), (override)); + +}; + +TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElementsWithStorage) { + ::testing::InSequence seq; + SuplaDeviceClass sd; + TimerMock timer; + StorageMock2 storage; + + ASSERT_EQ(Supla::Element::begin(), nullptr); + EXPECT_CALL(storage, init()); + EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true));; + EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(false)); + + EXPECT_CALL(timer, initTimers()); + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); +} + +TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceNoElementsWithStorageAndDataLoadAttempt) { + ::testing::InSequence seq; + SuplaDeviceClass sd; + TimerMock timer; + StorageMock2 storage; + + ASSERT_EQ(Supla::Element::begin(), nullptr); + EXPECT_CALL(storage, init()); + EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); + EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); + EXPECT_CALL(storage, prepareState(false)); + + EXPECT_CALL(timer, initTimers()); + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); +} + +TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceWithElements) { + ::testing::InSequence seq; + SuplaDeviceClass sd; + TimerMock timer; + ElementMock el1; + ElementMock el2; + + ASSERT_NE(Supla::Element::begin(), nullptr); + + EXPECT_CALL(el1, onInit()); + EXPECT_CALL(el2, onInit()); + + EXPECT_CALL(timer, initTimers()); + EXPECT_CALL(el1, onTimer()); + EXPECT_CALL(el2, onTimer()); + EXPECT_CALL(el1, onFastTimer()); + EXPECT_CALL(el2, onFastTimer()); + + + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); + sd.onTimer(); + sd.onFastTimer(); +} + +TEST_F(SuplaDeviceTests, StartWithoutNetworkInterfaceWithElementsWithStorage) { + ::testing::InSequence seq; + StorageMock2 storage; + SuplaDeviceClass sd; + TimerMock timer; + ElementMock el1; + ElementMock el2; + + ASSERT_NE(Supla::Element::begin(), nullptr); + + EXPECT_CALL(storage, init()); + EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); + EXPECT_CALL(el1, onSaveState()); + EXPECT_CALL(el2, onSaveState()); + + EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); + EXPECT_CALL(storage, prepareState(false)); + EXPECT_CALL(el1, onLoadState()); + EXPECT_CALL(el2, onLoadState()); + + EXPECT_CALL(el1, onInit()); + EXPECT_CALL(el2, onInit()); + + EXPECT_CALL(timer, initTimers()); + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_NETWORK_INTERFACE); +} + +class NetworkMock : public Supla::Network { + public: + NetworkMock() : Supla::Network(nullptr) {}; + MOCK_METHOD(int, read, (void *, int ), (override)); + MOCK_METHOD(int, write, (void *, int ), (override)); + MOCK_METHOD(int, connect, (const char *, int), (override)); + MOCK_METHOD(bool, connected, (), (override)); + MOCK_METHOD(void, disconnect, (), (override)); + MOCK_METHOD(void, setup, (), (override)); + MOCK_METHOD(void, setTimeout, (int), (override)); + + MOCK_METHOD(bool, isReady, (), (override)); + MOCK_METHOD(bool, iterate, (), (override)); + MOCK_METHOD(bool, ping, (void *), (override)); + +}; + +TEST_F(SuplaDeviceTests, BeginStopsAtEmptyGUID) { + ::testing::InSequence seq; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + + EXPECT_CALL(timer, initTimers()); + + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_GUID); +} + +TEST_F(SuplaDeviceTests, BeginStopsAtEmptyServer) { + ::testing::InSequence seq; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + + EXPECT_CALL(timer, initTimers()); + + char GUID[SUPLA_GUID_SIZE] = {1}; + sd.setGUID(GUID); + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN_SERVER_ADDRESS); +} + +TEST_F(SuplaDeviceTests, BeginStopsAtEmptyEmail) { + ::testing::InSequence seq; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + + EXPECT_CALL(timer, initTimers()); + + char GUID[SUPLA_GUID_SIZE] = {1}; + sd.setGUID(GUID); + sd.setServer("supla.rulez"); + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_MISSING_CREDENTIALS); +} + + +TEST_F(SuplaDeviceTests, BeginStopsAtEmptyAuthkey) { + ::testing::InSequence seq; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + + EXPECT_CALL(timer, initTimers()); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; + sd.setGUID(GUID); + sd.setServer("supla.rulez"); + sd.setEmail("john@supla"); + EXPECT_FALSE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); +} + +TEST_F(SuplaDeviceTests, SuccessfulBegin) { + ::testing::InSequence seq; + SrpcMock srpc; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + int dummy; + + EXPECT_CALL(timer, initTimers()); + EXPECT_CALL(net, setup()); + EXPECT_CALL(srpc, srpc_params_init(_)); + EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); + EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; + sd.setGUID(GUID); + sd.setServer("supla.rulez"); + sd.setEmail("john@supla"); + sd.setAuthKey(AUTHKEY); + EXPECT_TRUE(sd.begin()); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); +} + + + +TEST_F(SuplaDeviceTests, SuccessfulBeginAlternative) { + ::testing::InSequence seq; + SrpcMock srpc; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + int dummy; + + EXPECT_CALL(timer, initTimers()); + EXPECT_CALL(net, setup()); + EXPECT_CALL(srpc, srpc_params_init(_)); + EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); + EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; + EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); +} + + +TEST_F(SuplaDeviceTests, FailedBeginAlternativeOnEmptyAUTHKEY) { + ::testing::InSequence seq; + SrpcMock srpc; + NetworkMock net; + TimerMock timer; + + SuplaDeviceClass sd; + int dummy; + + EXPECT_CALL(timer, initTimers()); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0}; + EXPECT_FALSE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); +} + +TEST_F(SuplaDeviceTests, TwoChannelElementsNoNetworkWithStorage) { + SrpcMock srpc; + NetworkMock net; + StorageMock2 storage; + TimerMock timer; + TimeInterfaceStub time; + SuplaDeviceClass sd; + ElementMock el1; + ElementMock el2; + int dummy; + EXPECT_CALL(storage, prepareState(true)).WillOnce(Return(true)); + EXPECT_CALL(storage, init()); + EXPECT_CALL(el1, onSaveState()); + EXPECT_CALL(el2, onSaveState()); + + EXPECT_CALL(storage, finalizeSaveState()).WillOnce(Return(true)); + EXPECT_CALL(storage, prepareState(false)); + EXPECT_CALL(el1, onLoadState()); + EXPECT_CALL(el2, onLoadState()); + + EXPECT_CALL(el1, onInit()); + EXPECT_CALL(el2, onInit()); + + EXPECT_CALL(timer, initTimers()); + EXPECT_CALL(net, setup()); + EXPECT_CALL(srpc, srpc_params_init(_)); + EXPECT_CALL(srpc, srpc_init(_)).WillOnce(Return(&dummy)); + EXPECT_CALL(srpc, srpc_set_proto_version(&dummy, 16)); + + char GUID[SUPLA_GUID_SIZE] = {1}; + char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {2}; + EXPECT_TRUE(sd.begin(GUID, "supla.rulez", "superman@supla.org", AUTHKEY)); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INITIALIZED); + EXPECT_CALL(el1, iterateAlways()).Times(2); + EXPECT_CALL(el2, iterateAlways()).Times(2); + EXPECT_CALL(net, isReady()).WillRepeatedly(Return(false)); + + EXPECT_CALL(storage, prepareState(false)); + EXPECT_CALL(el1, onSaveState()); + EXPECT_CALL(el2, onSaveState()); + EXPECT_CALL(storage, finalizeSaveState()); + + for (int i = 0; i < 2; i++) sd.iterate(); +} + +TEST_F(SuplaDeviceTests, OnVersionErrorShouldCallDisconnect) { + NetworkMock net; + TimeInterfaceStub time; + + EXPECT_CALL(net, disconnect()).Times(1); + + SuplaDeviceClass sd; + TSDC_SuplaVersionError versionError{}; + + sd.onVersionError(&versionError); + EXPECT_EQ(sd.getCurrentStatus(), STATUS_PROTOCOL_VERSION_ERROR); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultOK) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_TRUE; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTERED_AND_READY); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultBadCredentials) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_BAD_CREDENTIALS; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_BAD_CREDENTIALS); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultTemporairlyUnavailable) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_TEMPORARILY_UNAVAILABLE); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultLocationConflict) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_LOCATION_CONFLICT; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_LOCATION_CONFLICT); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultChannelConflict) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_CHANNEL_CONFLICT; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_CHANNEL_CONFLICT); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultDeviceDisabled) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_DEVICE_DISABLED; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_DEVICE_IS_DISABLED); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultLocationDisabled) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_LOCATION_DISABLED; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_LOCATION_IS_DISABLED); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultDeviceLimitExceeded) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_DEVICE_LIMIT_EXCEEDED); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultGuidError) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_GUID_ERROR; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_GUID); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultAuthKeyError) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_AUTHKEY_ERROR; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_INVALID_AUTHKEY); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultRegistrationDisabled) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_REGISTRATION_DISABLED; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_REGISTRATION_DISABLED); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultNoLocationAvailable) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_NO_LOCATION_AVAILABLE); +} + +TEST_F(SuplaDeviceTests, OnRegisterResultUnknownError) { + NetworkMock net; + SrpcMock srpc; + TimeInterfaceStub time; + SuplaDeviceClass sd; + + EXPECT_CALL(srpc, srpc_dcs_async_set_activity_timeout(_, _)).Times(0); + EXPECT_CALL(net, disconnect()).Times(1); + + TSD_SuplaRegisterDeviceResult register_device_result{}; + register_device_result.result_code = 666; + register_device_result.activity_timeout = 45; + register_device_result.version = 16; + register_device_result.version_min = 1; + + sd.onRegisterResult(®ister_device_result); + + EXPECT_EQ(sd.getCurrentStatus(), STATUS_UNKNOWN_ERROR); +} diff --git a/lib/SuplaDevice/extras/test/doubles/element_mock.h b/lib/SuplaDevice/extras/test/doubles/element_mock.h index 54932347..4df9934f 100644 --- a/lib/SuplaDevice/extras/test/doubles/element_mock.h +++ b/lib/SuplaDevice/extras/test/doubles/element_mock.h @@ -1,39 +1,39 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _supla_element_mock_h -#define _supla_element_mock_h - -#include -#include - -class ElementMock : public Supla::Element { - public: - MOCK_METHOD(void, onInit, (), (override)); - MOCK_METHOD(void, onLoadState, (), (override)); - MOCK_METHOD(void, onSaveState, (), (override)); - MOCK_METHOD(void, onRegistered, (), (override)); - MOCK_METHOD(void, iterateAlways, (), (override)); - MOCK_METHOD(bool, iterateConnected, (void *), (override)); - MOCK_METHOD(void, onTimer, (), (override)); - MOCK_METHOD(void, onFastTimer, (), (override)); - MOCK_METHOD(int, handleNewValueFromServer, (TSD_SuplaChannelNewValue *), (override)); - MOCK_METHOD(void, handleGetChannelState, (TDSC_ChannelState &), (override)); - MOCK_METHOD(int, handleCalcfgFromServer, (TSD_DeviceCalCfgRequest *), (override)); - -}; - -#endif /*_supla_element_mock_h*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _supla_element_mock_h +#define _supla_element_mock_h + +#include +#include + +class ElementMock : public Supla::Element { + public: + MOCK_METHOD(void, onInit, (), (override)); + MOCK_METHOD(void, onLoadState, (), (override)); + MOCK_METHOD(void, onSaveState, (), (override)); + MOCK_METHOD(void, onRegistered, (), (override)); + MOCK_METHOD(void, iterateAlways, (), (override)); + MOCK_METHOD(bool, iterateConnected, (void *), (override)); + MOCK_METHOD(void, onTimer, (), (override)); + MOCK_METHOD(void, onFastTimer, (), (override)); + MOCK_METHOD(int, handleNewValueFromServer, (TSD_SuplaChannelNewValue *), (override)); + MOCK_METHOD(void, handleGetChannelState, (TDSC_ChannelState &), (override)); + MOCK_METHOD(int, handleCalcfgFromServer, (TSD_DeviceCalCfgRequest *), (override)); + +}; + +#endif /*_supla_element_mock_h*/ diff --git a/lib/SuplaDevice/extras/test/doubles/srpc_mock.cpp b/lib/SuplaDevice/extras/test/doubles/srpc_mock.cpp index 7a9f572c..cc8efda4 100644 --- a/lib/SuplaDevice/extras/test/doubles/srpc_mock.cpp +++ b/lib/SuplaDevice/extras/test/doubles/srpc_mock.cpp @@ -1,145 +1,145 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include "srpc_mock.h" - -_supla_int_t srpc_ds_async_channel_extendedvalue_changed( - void *_srpc, unsigned char channel_number, - TSuplaChannelExtendedValue *value) { - return 0; -} - -_supla_int_t srpc_ds_async_action_trigger( - void *_srpc, TDS_ActionTrigger *at) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->actionTrigger(at->ChannelNumber, at->ActionTrigger); -} - -_supla_int_t srpc_ds_async_get_channel_config(void *_srpc, - TDS_GetChannelConfigRequest *request) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->getChannelConfig(request->ChannelNumber); -} - -_supla_int_t srpc_ds_async_channel_value_changed_c( - void *_srpc, unsigned char channel_number, char *value, - unsigned char offline, unsigned _supla_int_t validity_time_sec) { - assert(SrpcInterface::instance); - std::vector vec(value, value + 8); - return SrpcInterface::instance->valueChanged(_srpc, channel_number, vec, offline, validity_time_sec); -} - -_supla_int_t srpc_dcs_async_set_activity_timeout( - void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_dcs_async_set_activity_timeout(_srpc, dcs_set_activity_timeout); -} - -void srpc_params_init(TsrpcParams *params) { - assert(SrpcInterface::instance); - SrpcInterface::instance->srpc_params_init(params); -} - -_supla_int_t srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, _supla_int_t SenderID, char Success) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_ds_async_set_channel_result(_srpc, ChannelNumber, SenderID, Success); -} - -_supla_int_t srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_ds_async_device_calcfg_result(_srpc, result); -} - -void *srpc_init(TsrpcParams *params) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_init(params); -} - -void srpc_rd_free(TsrpcReceivedData *rd) { - assert(SrpcInterface::instance); - SrpcInterface::instance->srpc_rd_free(rd); -} - -char srpc_getdata(void *_srpc, TsrpcReceivedData *rd, unsigned _supla_int_t rr_id) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_getdata(_srpc, rd, rr_id); -} - -char srpc_iterate(void *_srpc) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_iterate(_srpc); -} - -void srpc_set_proto_version(void *_srpc, unsigned char version) { - assert(SrpcInterface::instance); - SrpcInterface::instance->srpc_set_proto_version(_srpc, version); -} - -_supla_int_t srpc_ds_async_registerdevice_e(void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_ds_async_registerdevice_e(_srpc, registerdevice); -} - -_supla_int_t srpc_dcs_async_ping_server(void *_srpc) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_dcs_async_ping_server(_srpc); -} - -_supla_int_t srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_csd_async_channel_state_result(_srpc, state); -} - -_supla_int_t srpc_dcs_async_get_user_localtime(void *_srpc) { - assert(SrpcInterface::instance); - return SrpcInterface::instance->srpc_dcs_async_get_user_localtime(_srpc); -} - -SrpcInterface::SrpcInterface() { - instance = this; -} - -SrpcInterface::~SrpcInterface() { - instance = nullptr; -} - -SrpcInterface *SrpcInterface::instance = nullptr; - -// method copied directly from srpc.c -_supla_int_t srpc_evtool_v2_emextended2extended( - TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev) { - if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || - em_ev->m_count < 0) { - return 0; - } - - memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); - ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2; - - ev->size = sizeof(TElectricityMeter_ExtendedValue_V2) - - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + - sizeof(TElectricityMeter_Measurement) * em_ev->m_count; - - if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { - memcpy(ev->value, em_ev, ev->size); - return 1; - } - - ev->size = 0; - return 0; -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include "srpc_mock.h" + +_supla_int_t srpc_ds_async_channel_extendedvalue_changed( + void *_srpc, unsigned char channel_number, + TSuplaChannelExtendedValue *value) { + return 0; +} + +_supla_int_t srpc_ds_async_action_trigger( + void *_srpc, TDS_ActionTrigger *at) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->actionTrigger(at->ChannelNumber, at->ActionTrigger); +} + +_supla_int_t srpc_ds_async_get_channel_config(void *_srpc, + TDS_GetChannelConfigRequest *request) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->getChannelConfig(request->ChannelNumber); +} + +_supla_int_t srpc_ds_async_channel_value_changed_c( + void *_srpc, unsigned char channel_number, char *value, + unsigned char offline, unsigned _supla_int_t validity_time_sec) { + assert(SrpcInterface::instance); + std::vector vec(value, value + 8); + return SrpcInterface::instance->valueChanged(_srpc, channel_number, vec, offline, validity_time_sec); +} + +_supla_int_t srpc_dcs_async_set_activity_timeout( + void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_dcs_async_set_activity_timeout(_srpc, dcs_set_activity_timeout); +} + +void srpc_params_init(TsrpcParams *params) { + assert(SrpcInterface::instance); + SrpcInterface::instance->srpc_params_init(params); +} + +_supla_int_t srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, _supla_int_t SenderID, char Success) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_ds_async_set_channel_result(_srpc, ChannelNumber, SenderID, Success); +} + +_supla_int_t srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_ds_async_device_calcfg_result(_srpc, result); +} + +void *srpc_init(TsrpcParams *params) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_init(params); +} + +void srpc_rd_free(TsrpcReceivedData *rd) { + assert(SrpcInterface::instance); + SrpcInterface::instance->srpc_rd_free(rd); +} + +char srpc_getdata(void *_srpc, TsrpcReceivedData *rd, unsigned _supla_int_t rr_id) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_getdata(_srpc, rd, rr_id); +} + +char srpc_iterate(void *_srpc) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_iterate(_srpc); +} + +void srpc_set_proto_version(void *_srpc, unsigned char version) { + assert(SrpcInterface::instance); + SrpcInterface::instance->srpc_set_proto_version(_srpc, version); +} + +_supla_int_t srpc_ds_async_registerdevice_e(void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_ds_async_registerdevice_e(_srpc, registerdevice); +} + +_supla_int_t srpc_dcs_async_ping_server(void *_srpc) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_dcs_async_ping_server(_srpc); +} + +_supla_int_t srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_csd_async_channel_state_result(_srpc, state); +} + +_supla_int_t srpc_dcs_async_get_user_localtime(void *_srpc) { + assert(SrpcInterface::instance); + return SrpcInterface::instance->srpc_dcs_async_get_user_localtime(_srpc); +} + +SrpcInterface::SrpcInterface() { + instance = this; +} + +SrpcInterface::~SrpcInterface() { + instance = nullptr; +} + +SrpcInterface *SrpcInterface::instance = nullptr; + +// method copied directly from srpc.c +_supla_int_t srpc_evtool_v2_emextended2extended( + TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev) { + if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || + em_ev->m_count < 0) { + return 0; + } + + memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); + ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2; + + ev->size = sizeof(TElectricityMeter_ExtendedValue_V2) - + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + + sizeof(TElectricityMeter_Measurement) * em_ev->m_count; + + if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { + memcpy(ev->value, em_ev, ev->size); + return 1; + } + + ev->size = 0; + return 0; +} + diff --git a/lib/SuplaDevice/extras/test/doubles/srpc_mock.h b/lib/SuplaDevice/extras/test/doubles/srpc_mock.h index 61f72783..14b65f78 100644 --- a/lib/SuplaDevice/extras/test/doubles/srpc_mock.h +++ b/lib/SuplaDevice/extras/test/doubles/srpc_mock.h @@ -1,85 +1,85 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _srpc_mock_h -#define _srpc_mock_h - -#include -#include -#include - -#include - -class SrpcInterface { - public: - SrpcInterface(); - virtual ~SrpcInterface(); - - virtual _supla_int_t valueChanged(void *srpc, - unsigned char channelNumber, - std::vector value, - unsigned char offline, - unsigned _supla_int_t - validity_time_sec) = 0; - - virtual _supla_int_t actionTrigger(unsigned char channel_number, int actionTrigger) = 0; - - virtual _supla_int_t srpc_dcs_async_set_activity_timeout(void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) = 0; - virtual void srpc_params_init(TsrpcParams *params) = 0; - virtual _supla_int_t srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, _supla_int_t SenderID, char Success) = 0; - virtual _supla_int_t srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result) = 0; - virtual void *srpc_init(TsrpcParams *params) = 0; - virtual void srpc_rd_free(TsrpcReceivedData *rd) = 0; - virtual char srpc_getdata(void *_srpc, TsrpcReceivedData *rd, unsigned _supla_int_t rr_id) = 0; - virtual char srpc_iterate(void *_srpc) = 0; - virtual void srpc_set_proto_version(void *_srpc, unsigned char version) = 0; - virtual _supla_int_t srpc_ds_async_registerdevice_e(void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) = 0; - virtual _supla_int_t srpc_dcs_async_ping_server(void *_srpc) = 0; - virtual _supla_int_t srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) = 0; - virtual _supla_int_t srpc_dcs_async_get_user_localtime(void *_srpc) = 0; - virtual _supla_int_t getChannelConfig(unsigned char channelNumber) = 0; - - static SrpcInterface *instance; -}; - -class SrpcMock : public SrpcInterface { - public: - MOCK_METHOD(_supla_int_t, - valueChanged, - (void *, - unsigned char, - std::vector, - unsigned char, - unsigned _supla_int_t), - (override)); - MOCK_METHOD(_supla_int_t, srpc_dcs_async_set_activity_timeout, (void *, TDCS_SuplaSetActivityTimeout *), (override)); - MOCK_METHOD(void, srpc_params_init, (TsrpcParams *), (override)); - MOCK_METHOD(_supla_int_t, srpc_ds_async_set_channel_result, (void *, unsigned char, _supla_int_t, char), (override)); - MOCK_METHOD(_supla_int_t, srpc_ds_async_device_calcfg_result, (void *, TDS_DeviceCalCfgResult *), (override)); - MOCK_METHOD((void *), srpc_init, (TsrpcParams *), (override)); - MOCK_METHOD(void, srpc_rd_free, (TsrpcReceivedData *), (override)); - MOCK_METHOD(char, srpc_getdata, (void *, TsrpcReceivedData *, unsigned _supla_int_t), (override)); - MOCK_METHOD(char, srpc_iterate, (void *), (override)); - MOCK_METHOD(void, srpc_set_proto_version, (void *, unsigned char), (override)); - MOCK_METHOD(_supla_int_t, srpc_ds_async_registerdevice_e, (void *, TDS_SuplaRegisterDevice_E *), (override)); - MOCK_METHOD(_supla_int_t, srpc_dcs_async_ping_server, (void *), (override)); - MOCK_METHOD(_supla_int_t, srpc_csd_async_channel_state_result, (void *, TDSC_ChannelState *), (override)); - MOCK_METHOD(_supla_int_t, srpc_dcs_async_get_user_localtime, (void *), (override)); - MOCK_METHOD(_supla_int_t, actionTrigger, (unsigned char channel_number, int actionTrigger), (override)); - MOCK_METHOD(_supla_int_t, getChannelConfig, (unsigned char channelNumber), (override)); -}; - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _srpc_mock_h +#define _srpc_mock_h + +#include +#include +#include + +#include + +class SrpcInterface { + public: + SrpcInterface(); + virtual ~SrpcInterface(); + + virtual _supla_int_t valueChanged(void *srpc, + unsigned char channelNumber, + std::vector value, + unsigned char offline, + unsigned _supla_int_t + validity_time_sec) = 0; + + virtual _supla_int_t actionTrigger(unsigned char channel_number, int actionTrigger) = 0; + + virtual _supla_int_t srpc_dcs_async_set_activity_timeout(void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) = 0; + virtual void srpc_params_init(TsrpcParams *params) = 0; + virtual _supla_int_t srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, _supla_int_t SenderID, char Success) = 0; + virtual _supla_int_t srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result) = 0; + virtual void *srpc_init(TsrpcParams *params) = 0; + virtual void srpc_rd_free(TsrpcReceivedData *rd) = 0; + virtual char srpc_getdata(void *_srpc, TsrpcReceivedData *rd, unsigned _supla_int_t rr_id) = 0; + virtual char srpc_iterate(void *_srpc) = 0; + virtual void srpc_set_proto_version(void *_srpc, unsigned char version) = 0; + virtual _supla_int_t srpc_ds_async_registerdevice_e(void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) = 0; + virtual _supla_int_t srpc_dcs_async_ping_server(void *_srpc) = 0; + virtual _supla_int_t srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) = 0; + virtual _supla_int_t srpc_dcs_async_get_user_localtime(void *_srpc) = 0; + virtual _supla_int_t getChannelConfig(unsigned char channelNumber) = 0; + + static SrpcInterface *instance; +}; + +class SrpcMock : public SrpcInterface { + public: + MOCK_METHOD(_supla_int_t, + valueChanged, + (void *, + unsigned char, + std::vector, + unsigned char, + unsigned _supla_int_t), + (override)); + MOCK_METHOD(_supla_int_t, srpc_dcs_async_set_activity_timeout, (void *, TDCS_SuplaSetActivityTimeout *), (override)); + MOCK_METHOD(void, srpc_params_init, (TsrpcParams *), (override)); + MOCK_METHOD(_supla_int_t, srpc_ds_async_set_channel_result, (void *, unsigned char, _supla_int_t, char), (override)); + MOCK_METHOD(_supla_int_t, srpc_ds_async_device_calcfg_result, (void *, TDS_DeviceCalCfgResult *), (override)); + MOCK_METHOD((void *), srpc_init, (TsrpcParams *), (override)); + MOCK_METHOD(void, srpc_rd_free, (TsrpcReceivedData *), (override)); + MOCK_METHOD(char, srpc_getdata, (void *, TsrpcReceivedData *, unsigned _supla_int_t), (override)); + MOCK_METHOD(char, srpc_iterate, (void *), (override)); + MOCK_METHOD(void, srpc_set_proto_version, (void *, unsigned char), (override)); + MOCK_METHOD(_supla_int_t, srpc_ds_async_registerdevice_e, (void *, TDS_SuplaRegisterDevice_E *), (override)); + MOCK_METHOD(_supla_int_t, srpc_dcs_async_ping_server, (void *), (override)); + MOCK_METHOD(_supla_int_t, srpc_csd_async_channel_state_result, (void *, TDSC_ChannelState *), (override)); + MOCK_METHOD(_supla_int_t, srpc_dcs_async_get_user_localtime, (void *), (override)); + MOCK_METHOD(_supla_int_t, actionTrigger, (unsigned char channel_number, int actionTrigger), (override)); + MOCK_METHOD(_supla_int_t, getChannelConfig, (unsigned char channelNumber), (override)); +}; + +#endif diff --git a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.cpp b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.cpp index 34d8eed8..214b3a54 100644 --- a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.cpp +++ b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.cpp @@ -1,90 +1,90 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "MAXThermocouple.h" - -namespace Supla { -namespace Sensor { -MAXThermocouple::MAXThermocouple(uint8_t pin_CLK, uint8_t pin_CS, uint8_t pin_DO) - : pin_CLK(pin_CLK), pin_CS(pin_CS), pin_DO(pin_DO) { -} - -double MAXThermocouple::getValue() { - int32_t value; - - digitalWrite(pin_CS, LOW); - delay(1); - - value = spiRead(); - - digitalWrite(pin_CS, HIGH); - - if ((value >> 16) == (value & 0xffff)) { // MAX6675 - value >>= 16; - - if ((value & 0x4) || (value <= 0)) { // this means there is no probe connected to Max6675 - Serial.println(F("Max6675 Error")); - return TEMPERATURE_NOT_AVAILABLE; - } - value >>= 3; - - return (double)value * 0.25; - - } else { // MAX31855 - - if (value & 0x7) { - Serial.println(F("Max31855 Error")); - return TEMPERATURE_NOT_AVAILABLE; - } else { - uint16_t _internTemp = (value >> 4) & 0xfff; - - value >>= 18; - if (value & 0x2000) { // is - - value |= 0xffffc000; - } - - return (double)value * 0.25; - } - } -} - -void MAXThermocouple::onInit() { - digitalWrite(pin_CS, HIGH); - - pinMode(pin_CS, OUTPUT); - pinMode(pin_CLK, OUTPUT); - pinMode(pin_DO, INPUT); - - channel.setNewValue(getValue()); -} - -uint32_t MAXThermocouple::spiRead() { - uint32_t d = 0; - - for (int i = 31; i >= 0; i--) { - digitalWrite(pin_CLK, LOW); - delay(1); - d <<= 1; - d |= digitalRead(pin_DO); - - digitalWrite(pin_CLK, HIGH); - delay(1); - } - return d; -} - -}; // namespace Sensor -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "MAXThermocouple.h" + +namespace Supla { +namespace Sensor { +MAXThermocouple::MAXThermocouple(uint8_t pin_CLK, uint8_t pin_CS, uint8_t pin_DO) + : pin_CLK(pin_CLK), pin_CS(pin_CS), pin_DO(pin_DO) { +} + +double MAXThermocouple::getValue() { + int32_t value; + + digitalWrite(pin_CS, LOW); + delay(1); + + value = spiRead(); + + digitalWrite(pin_CS, HIGH); + + if ((value >> 16) == (value & 0xffff)) { // MAX6675 + value >>= 16; + + if ((value & 0x4) || (value <= 0)) { // this means there is no probe connected to Max6675 + Serial.println(F("Max6675 Error")); + return TEMPERATURE_NOT_AVAILABLE; + } + value >>= 3; + + return (double)value * 0.25; + + } else { // MAX31855 + + if (value & 0x7) { + Serial.println(F("Max31855 Error")); + return TEMPERATURE_NOT_AVAILABLE; + } else { + uint16_t _internTemp = (value >> 4) & 0xfff; + + value >>= 18; + if (value & 0x2000) { // is - + value |= 0xffffc000; + } + + return (double)value * 0.25; + } + } +} + +void MAXThermocouple::onInit() { + digitalWrite(pin_CS, HIGH); + + pinMode(pin_CS, OUTPUT); + pinMode(pin_CLK, OUTPUT); + pinMode(pin_DO, INPUT); + + channel.setNewValue(getValue()); +} + +uint32_t MAXThermocouple::spiRead() { + uint32_t d = 0; + + for (int i = 31; i >= 0; i--) { + digitalWrite(pin_CLK, LOW); + delay(1); + d <<= 1; + d |= digitalRead(pin_DO); + + digitalWrite(pin_CLK, HIGH); + delay(1); + } + return d; +} + +}; // namespace Sensor +}; // namespace Supla diff --git a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.h b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.h index 1f20260e..e83ef3f4 100644 --- a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.h +++ b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/MAXThermocouple.h @@ -1,43 +1,43 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _maxThermocouple_k_h -#define _maxThermocouple_k_h - -#include -#include - -namespace Supla { -namespace Sensor { -class MAXThermocouple : public Thermometer { - public: - MAXThermocouple(uint8_t pin_CLK, uint8_t pin_CS, uint8_t pin_DO); - double getValue(); - - private: - void onInit(); - uint32_t spiRead(void); - - protected: - int8_t pin_CLK; - int8_t pin_CS; - int8_t pin_DO; -}; - -}; // namespace Sensor -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _maxThermocouple_k_h +#define _maxThermocouple_k_h + +#include +#include + +namespace Supla { +namespace Sensor { +class MAXThermocouple : public Thermometer { + public: + MAXThermocouple(uint8_t pin_CLK, uint8_t pin_CS, uint8_t pin_DO); + double getValue(); + + private: + void onInit(); + uint32_t spiRead(void); + + protected: + int8_t pin_CLK; + int8_t pin_CS; + int8_t pin_DO; +}; + +}; // namespace Sensor +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.cpp b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.cpp index 13eca948..1195ee96 100644 --- a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.cpp +++ b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.cpp @@ -1,18 +1,18 @@ -#include "hygro_meter.h" - -Supla::Sensor::HygroMeter::HygroMeter() { - channel.setType(SUPLA_CHANNELTYPE_HUMIDITYSENSOR); - channel.setDefault(SUPLA_CHANNELFNC_HUMIDITY); -} - -double Supla::Sensor::HygroMeter::getHumi() { - return HUMIDITY_NOT_AVAILABLE; -} - -void Supla::Sensor::HygroMeter::iterateAlways() { - if (millis() - lastReadTime > 10000) { - lastReadTime = millis(); - channel.setNewValue(TEMPERATURE_NOT_AVAILABLE, getHumi()); - } -} - +#include "hygro_meter.h" + +Supla::Sensor::HygroMeter::HygroMeter() { + channel.setType(SUPLA_CHANNELTYPE_HUMIDITYSENSOR); + channel.setDefault(SUPLA_CHANNELFNC_HUMIDITY); +} + +double Supla::Sensor::HygroMeter::getHumi() { + return HUMIDITY_NOT_AVAILABLE; +} + +void Supla::Sensor::HygroMeter::iterateAlways() { + if (millis() - lastReadTime > 10000) { + lastReadTime = millis(); + channel.setNewValue(TEMPERATURE_NOT_AVAILABLE, getHumi()); + } +} + diff --git a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.h b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.h index 407d3961..3c817273 100644 --- a/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.h +++ b/lib/SuplaDevice/libraries/SuplaDevice/src/supla/sensor/hygro_meter.h @@ -1,22 +1,22 @@ -#ifndef _hygro_meter_h -#define _hygro_meter_h - -#include "thermometer.h" - -#define HUMIDITY_NOT_AVAILABLE -1 - -namespace Supla { -namespace Sensor { -class HygroMeter : public Thermometer { - public: - HygroMeter(); - virtual double getHumi(); - void iterateAlways(); - -}; - -}; // namespace Sensor -}; // namespace Supla - -#endif - +#ifndef _hygro_meter_h +#define _hygro_meter_h + +#include "thermometer.h" + +#define HUMIDITY_NOT_AVAILABLE -1 + +namespace Supla { +namespace Sensor { +class HygroMeter : public Thermometer { + public: + HygroMeter(); + virtual double getHumi(); + void iterateAlways(); + +}; + +}; // namespace Sensor +}; // namespace Supla + +#endif + diff --git a/lib/SuplaDevice/src/CMakeLists.txt b/lib/SuplaDevice/src/CMakeLists.txt index f7472796..7b00fd30 100644 --- a/lib/SuplaDevice/src/CMakeLists.txt +++ b/lib/SuplaDevice/src/CMakeLists.txt @@ -1,51 +1,51 @@ -set(SRCS - supla/uptime.cpp - supla/channel.cpp - supla/channel_extended.cpp - supla/io.cpp - supla/tools.cpp - supla/element.cpp - supla/local_action.cpp - supla/channel_element.cpp - supla/correction.cpp - supla/at_channel.cpp - supla/action_handler.cpp - - supla/storage/storage.cpp - - supla/control/internal_pin_output.cpp - supla/control/pin_status_led.cpp - supla/control/rgbw_base.cpp - supla/control/rgb_base.cpp - supla/control/dimmer_base.cpp - supla/control/rgbw_leds.cpp - supla/control/rgb_leds.cpp - supla/control/dimmer_leds.cpp - supla/control/simple_button.cpp - supla/control/button.cpp - supla/control/action_trigger.cpp - supla/control/relay.cpp - supla/control/virtual_relay.cpp - - supla/condition.cpp - supla/condition_getter.cpp - supla/conditions/on_less.cpp - supla/conditions/on_less_eq.cpp - supla/conditions/on_greater.cpp - supla/conditions/on_greater_eq.cpp - supla/conditions/on_between.cpp - supla/conditions/on_between_eq.cpp - supla/conditions/on_equal.cpp - supla/conditions/on_invalid.cpp - - SuplaDevice.cpp - supla/network/network.cpp - supla/clock/clock.cpp - - supla/sensor/therm_hygro_press_meter.cpp - supla/sensor/therm_hygro_meter.cpp - supla/sensor/thermometer.cpp - supla/sensor/electricity_meter.cpp -) - -add_library(supladevicelib SHARED ${SRCS}) +set(SRCS + supla/uptime.cpp + supla/channel.cpp + supla/channel_extended.cpp + supla/io.cpp + supla/tools.cpp + supla/element.cpp + supla/local_action.cpp + supla/channel_element.cpp + supla/correction.cpp + supla/at_channel.cpp + supla/action_handler.cpp + + supla/storage/storage.cpp + + supla/control/internal_pin_output.cpp + supla/control/pin_status_led.cpp + supla/control/rgbw_base.cpp + supla/control/rgb_base.cpp + supla/control/dimmer_base.cpp + supla/control/rgbw_leds.cpp + supla/control/rgb_leds.cpp + supla/control/dimmer_leds.cpp + supla/control/simple_button.cpp + supla/control/button.cpp + supla/control/action_trigger.cpp + supla/control/relay.cpp + supla/control/virtual_relay.cpp + + supla/condition.cpp + supla/condition_getter.cpp + supla/conditions/on_less.cpp + supla/conditions/on_less_eq.cpp + supla/conditions/on_greater.cpp + supla/conditions/on_greater_eq.cpp + supla/conditions/on_between.cpp + supla/conditions/on_between_eq.cpp + supla/conditions/on_equal.cpp + supla/conditions/on_invalid.cpp + + SuplaDevice.cpp + supla/network/network.cpp + supla/clock/clock.cpp + + supla/sensor/therm_hygro_press_meter.cpp + supla/sensor/therm_hygro_meter.cpp + supla/sensor/thermometer.cpp + supla/sensor/electricity_meter.cpp +) + +add_library(supladevicelib SHARED ${SRCS}) diff --git a/lib/SuplaDevice/src/SuplaDevice.cpp b/lib/SuplaDevice/src/SuplaDevice.cpp index 0d1fd94f..7f68d7cd 100644 --- a/lib/SuplaDevice/src/SuplaDevice.cpp +++ b/lib/SuplaDevice/src/SuplaDevice.cpp @@ -1,552 +1,552 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include -#include - -#include "SuplaDevice.h" -#include "supla-common/IEEE754tools.h" -#include "supla-common/log.h" -#include "supla-common/srpc.h" -#include "supla/channel.h" -#include "supla/element.h" -#include "supla/io.h" -#include "supla/storage/storage.h" -#include "supla/timer.h" - -void SuplaDeviceClass::status(int newStatus, const char *msg, bool alwaysLog) { - bool showLog = false; - if (currentStatus != newStatus && !(newStatus == STATUS_REGISTER_IN_PROGRESS && currentStatus > STATUS_REGISTER_IN_PROGRESS)) { - if (impl_arduino_status != NULL) { - impl_arduino_status(newStatus, msg); - } - currentStatus = newStatus; - showLog = true; - } - if (alwaysLog || showLog) supla_log(LOG_DEBUG, "Current status: [%d] %s", newStatus, msg); -} - -SuplaDeviceClass::SuplaDeviceClass() - : port(-1), - connectionFailCounter(0), - networkIsNotReadyCounter(0), - currentStatus(STATUS_UNKNOWN), - impl_arduino_status(nullptr), - clock(nullptr) { - srpc = NULL; - registered = 0; - lastIterateTime = 0; - waitForIterate = 0; -} - -SuplaDeviceClass::~SuplaDeviceClass() { -} - -void SuplaDeviceClass::setStatusFuncImpl( - _impl_arduino_status impl_arduino_status) { - this->impl_arduino_status = impl_arduino_status; -} - -bool SuplaDeviceClass::isInitialized(bool msg) { - if (srpc != NULL) { - if (msg) - status(STATUS_ALREADY_INITIALIZED, "SuplaDevice is already initialized"); - - return true; - } - - return false; -} - -bool SuplaDeviceClass::begin(char GUID[SUPLA_GUID_SIZE], - const char *Server, - const char *email, - char authkey[SUPLA_AUTHKEY_SIZE], - unsigned char version) { - setGUID(GUID); - setServer(Server); - setEmail(email); - setAuthKey(authkey); - - return begin(version); -} - -bool SuplaDeviceClass::begin(unsigned char version) { - if (isInitialized(true)) return false; - supla_log(LOG_DEBUG, "Supla - starting initialization"); - - Supla::Storage::Init(); - - // Supla::Storage::LoadDeviceConfig(); - // Supla::Storage::LoadElementConfig(); - - // Pefrorm dry run of write state to validate stored state section with - // current device configuration - if (Supla::Storage::PrepareState(true)) { - Serial.println(F( - "Validating storage state section with current device configuration")); - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onSaveState(); - delay(0); - } - // If state storage validation was successful, perform read state - if (Supla::Storage::FinalizeSaveState()) { - Serial.println( - F("Storage state section validation completed. Loading elements " - "state...")); - // Iterate all elements and load state - Supla::Storage::PrepareState(); - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onLoadState(); - delay(0); - } - } - } else { - Serial.println(F("Storage not found. Running without state memory")); - } - - // Initialize elements - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onInit(); - delay(0); - } - - // Enable timers - Supla::initTimers(); - - if (Supla::Network::Instance() == NULL) { - status(STATUS_MISSING_NETWORK_INTERFACE, "Network Interface not defined!"); - return false; - } - - bool emptyGuidDetected = true; - for (int i = 0; i < SUPLA_GUID_SIZE; i++) { - if (Supla::Channel::reg_dev.GUID[i] != 0) { - emptyGuidDetected = false; - } - } - if (emptyGuidDetected) { - status(STATUS_INVALID_GUID, "Missing GUID"); - return false; - } - - if (Supla::Channel::reg_dev.ServerName[0] == '\0') { - status(STATUS_UNKNOWN_SERVER_ADDRESS, "Missing server address"); - return false; - } - - if (Supla::Channel::reg_dev.Email[0] == '\0') { - status(STATUS_MISSING_CREDENTIALS, "Missing email address"); - return false; - } - - bool emptyAuthKeyDetected = true; - for (int i = 0; i < SUPLA_AUTHKEY_SIZE; i++) { - if (Supla::Channel::reg_dev.AuthKey[i] != 0) { - emptyAuthKeyDetected = false; - break; - } - } - if (emptyAuthKeyDetected) { - status(STATUS_INVALID_AUTHKEY, "Missing AuthKey"); - return false; - } - - if (strnlen(Supla::Channel::reg_dev.Name, SUPLA_DEVICE_NAME_MAXSIZE) == 0) { -#if defined(ARDUINO_ARCH_ESP8266) - setString( - Supla::Channel::reg_dev.Name, "ESP8266", SUPLA_DEVICE_NAME_MAXSIZE); -#elif defined(ARDUINO_ARCH_ESP32) - setString(Supla::Channel::reg_dev.Name, "ESP32", SUPLA_DEVICE_NAME_MAXSIZE); -#else - setString( - Supla::Channel::reg_dev.Name, "ARDUINO", SUPLA_DEVICE_NAME_MAXSIZE); -#endif - } - - if (strnlen(Supla::Channel::reg_dev.SoftVer, SUPLA_SOFTVER_MAXSIZE) == 0) { - setString(Supla::Channel::reg_dev.SoftVer, - "User SW, lib 2.3.5", - SUPLA_SOFTVER_MAXSIZE); - } - - Serial.println(F("Initializing network layer")); - Supla::Network::Setup(); - - TsrpcParams srpc_params; - srpc_params_init(&srpc_params); - srpc_params.data_read = &Supla::data_read; - srpc_params.data_write = &Supla::data_write; - srpc_params.on_remote_call_received = &Supla::message_received; - srpc_params.user_params = this; - - srpc = srpc_init(&srpc_params); - - // Set Supla protocol interface version - srpc_set_proto_version(srpc, version); - - supla_log(LOG_DEBUG, "Using Supla protocol version %d", version); - - status(STATUS_INITIALIZED, "SuplaDevice initialized"); - return true; -} - -void SuplaDeviceClass::setName(const char *Name) { - if (isInitialized(true)) return; - setString(Supla::Channel::reg_dev.Name, Name, SUPLA_DEVICE_NAME_MAXSIZE); -} - -void SuplaDeviceClass::setString(char *dst, const char *src, int max_size) { - if (src == NULL) { - dst[0] = 0; - return; - } - - int size = strlen(src); - - if (size + 1 > max_size) size = max_size - 1; - - memcpy(dst, src, size); -} - -void SuplaDeviceClass::onTimer(void) { - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onTimer(); - } -} - -void SuplaDeviceClass::onFastTimer(void) { - // Iteration over all impulse counters will count incomming impulses. It is - // after SuplaDevice initialization (because we have to read stored counter - // values) and before any other operation like connection to Supla cloud - // (because we want to count impulses even when we have connection issues. - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onFastTimer(); - } -} - -void SuplaDeviceClass::iterate(void) { - if (!isInitialized(false)) return; - - unsigned long _millis = millis(); - unsigned long timeDiff = _millis - lastIterateTime; - - uptime.iterate(_millis); - - // Iterate all elements - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->iterateAlways(); - delay(0); - } - - // Iterate all elements and saves state - if (Supla::Storage::SaveStateAllowed(_millis)) { - Supla::Storage::PrepareState(); - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onSaveState(); - delay(0); - } - Supla::Storage::FinalizeSaveState(); - } - - if (waitForIterate != 0 && _millis < waitForIterate) { - return; - } else { - waitForIterate = 0; - } - - // Restart network after >1 min of failed connection attempts - if (connectionFailCounter > 30) { - connectionFailCounter = 0; - supla_log(LOG_DEBUG, - "Connection fail counter overflow. Trying to setup network " - "interface again"); - Supla::Network::Setup(); - return; - } - - if (!Supla::Network::IsReady()) { - uptime.setConnectionLostCause( - SUPLA_LASTCONNECTIONRESETCAUSE_WIFI_CONNECTION_LOST); - waitForIterate = _millis + 100; - status(STATUS_NETWORK_DISCONNECTED, "No connection to network"); - networkIsNotReadyCounter++; - if (networkIsNotReadyCounter > 20) { - networkIsNotReadyCounter = 0; - connectionFailCounter++; - } - return; - } - networkIsNotReadyCounter = 0; - - if (!Supla::Network::Connected()) { - - uptime.setConnectionLostCause( - SUPLA_LASTCONNECTIONRESETCAUSE_SERVER_CONNECTION_LOST); - - registered = 0; - - int result = - Supla::Network::Connect(Supla::Channel::reg_dev.ServerName, port); - if (1 == result) { - uptime.resetConnectionUptime(); - connectionFailCounter = 0; - supla_log(LOG_DEBUG, "Connected to Supla Server"); - } else { - status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); - supla_log(LOG_DEBUG, - "Connection fail (%d). Server: %s", - result, - Supla::Channel::reg_dev.ServerName); - - Supla::Network::Disconnect(); - waitForIterate = _millis + 2000; - connectionFailCounter++; - return; - } - } - - Supla::Network::Iterate(); - - if (srpc_iterate(srpc) == SUPLA_RESULT_FALSE) { - status(STATUS_ITERATE_FAIL, "Iterate fail"); - Supla::Network::Disconnect(); - - waitForIterate = _millis + 5000; - return; - } - - if (registered == 0) { - // Perform registration if we are not yet registered - registered = -1; - lastIterateTime = _millis; - status(STATUS_REGISTER_IN_PROGRESS, "Register in progress"); - if (!srpc_ds_async_registerdevice_e(srpc, &Supla::Channel::reg_dev)) { - supla_log(LOG_DEBUG, "Fatal SRPC failure!"); - } - } else if (registered == -1) { - // Handle registration timeout (in case of no reply received) - if (timeDiff > 10*1000) { - supla_log(LOG_DEBUG, "No reply to registration message. Resetting connection."); - status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); - Supla::Network::Disconnect(); - - waitForIterate = _millis + 2000; - connectionFailCounter++; - } - - } else if (registered == 1) { - // Device is registered and everything is correct - - if (Supla::Network::Ping(srpc) == false) { - uptime.setConnectionLostCause( - SUPLA_LASTCONNECTIONRESETCAUSE_ACTIVITY_TIMEOUT); - supla_log(LOG_DEBUG, "TIMEOUT - lost connection with server"); - status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); - Supla::Network::Disconnect(); - } - - if (timeDiff > 0) { - // Iterate all elements - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - if (!element->iterateConnected(srpc)) { - break; - } - delay(0); - } - - lastIterateTime = _millis; - } - } -} - -void SuplaDeviceClass::onVersionError(TSDC_SuplaVersionError *version_error) { - status(STATUS_PROTOCOL_VERSION_ERROR, "Protocol version error"); - Serial.print(F("Protocol version error. Server min: ")); - Serial.print(version_error->server_version_min); - Serial.print(F("; Server version: ")); - Serial.println(version_error->server_version); - - Supla::Network::Disconnect(); - - waitForIterate = millis() + 5000; -} - -void SuplaDeviceClass::onRegisterResult( - TSD_SuplaRegisterDeviceResult *register_device_result) { - _supla_int_t activity_timeout = 0; - - switch (register_device_result->result_code) { - // OK scenario - case SUPLA_RESULTCODE_TRUE: - activity_timeout = register_device_result->activity_timeout; - Supla::Network::Instance()->setActivityTimeout(activity_timeout); - registered = 1; - supla_log(LOG_DEBUG, - "Device registered (activity timeout %d s, server version: %d, " - "server min version: %d)", - register_device_result->activity_timeout, - register_device_result->version, - register_device_result->version_min); - lastIterateTime = millis(); - status(STATUS_REGISTERED_AND_READY, "Registered and ready"); - - if (activity_timeout != ACTIVITY_TIMEOUT) { - supla_log( - LOG_DEBUG, "Changing activity timeout to %d", ACTIVITY_TIMEOUT); - TDCS_SuplaSetActivityTimeout at; - at.activity_timeout = ACTIVITY_TIMEOUT; - srpc_dcs_async_set_activity_timeout(srpc, &at); - } - - for (auto element = Supla::Element::begin(); element != nullptr; - element = element->next()) { - element->onRegistered(); - delay(0); - } - - return; - - // NOK scenarios - case SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE: - status(STATUS_TEMPORARILY_UNAVAILABLE, "Temporarily unavailable!", true); - break; - - case SUPLA_RESULTCODE_GUID_ERROR: - status(STATUS_INVALID_GUID, "Incorrect device GUID!", true); - break; - - case SUPLA_RESULTCODE_AUTHKEY_ERROR: - status(STATUS_INVALID_AUTHKEY, "Incorrect AuthKey!", true); - break; - - case SUPLA_RESULTCODE_BAD_CREDENTIALS: - status(STATUS_BAD_CREDENTIALS, "Bad credentials - incorrect AuthKey or email", true); - break; - - case SUPLA_RESULTCODE_REGISTRATION_DISABLED: - status(STATUS_REGISTRATION_DISABLED, "Registration disabled!", true); - break; - - case SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED: - status(STATUS_DEVICE_LIMIT_EXCEEDED, "Device limit exceeded!", true); - break; - - case SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE: - status(STATUS_NO_LOCATION_AVAILABLE, "No location available!", true); - break; - - case SUPLA_RESULTCODE_DEVICE_DISABLED: - status(STATUS_DEVICE_IS_DISABLED, "Device is disabled!", true); - break; - - case SUPLA_RESULTCODE_LOCATION_DISABLED: - status(STATUS_LOCATION_IS_DISABLED, "Location is disabled!", true); - break; - - case SUPLA_RESULTCODE_LOCATION_CONFLICT: - status(STATUS_LOCATION_CONFLICT, "Location conflict!", true); - break; - - case SUPLA_RESULTCODE_CHANNEL_CONFLICT: - status(STATUS_CHANNEL_CONFLICT, "Channel conflict!", true); - break; - - default: - status(STATUS_UNKNOWN_ERROR, "Unknown registration error", true); - supla_log(LOG_ERR, - "Register result code %i", - register_device_result->result_code); - break; - } - - Supla::Network::Disconnect(); - waitForIterate = millis() + 5000; -} - -void SuplaDeviceClass::channelSetActivityTimeoutResult( - TSDC_SuplaSetActivityTimeoutResult *result) { - Supla::Network::Instance()->setActivityTimeout(result->activity_timeout); - supla_log( - LOG_DEBUG, "Activity timeout set to %d s", result->activity_timeout); -} - -void SuplaDeviceClass::setServerPort(int value) { - port = value; -} - -void SuplaDeviceClass::setSwVersion(const char *swVersion) { - setString(Supla::Channel::reg_dev.SoftVer, swVersion, SUPLA_SOFTVER_MAXSIZE); -} - -int SuplaDeviceClass::getCurrentStatus() { - return currentStatus; -} - -void SuplaDeviceClass::fillStateData(TDSC_ChannelState &channelState) { - channelState.Fields |= SUPLA_CHANNELSTATE_FIELD_UPTIME | - SUPLA_CHANNELSTATE_FIELD_CONNECTIONUPTIME; - - channelState.Uptime = uptime.getUptime(); - channelState.ConnectionUptime = uptime.getConnectionUptime(); - if (uptime.getLastResetCause() > 0) { - channelState.Fields |= SUPLA_CHANNELSTATE_FIELD_LASTCONNECTIONRESETCAUSE; - channelState.LastConnectionResetCause = uptime.getLastResetCause(); - } -} - -void SuplaDeviceClass::setGUID(char GUID[SUPLA_GUID_SIZE]) { - memcpy(Supla::Channel::reg_dev.GUID, GUID, SUPLA_GUID_SIZE); -} - -void SuplaDeviceClass::setAuthKey(char authkey[SUPLA_AUTHKEY_SIZE]) { - memcpy(Supla::Channel::reg_dev.AuthKey, authkey, SUPLA_AUTHKEY_SIZE); -} - -void SuplaDeviceClass::setEmail(const char *email) { - setString(Supla::Channel::reg_dev.Email, email, SUPLA_EMAIL_MAXSIZE); -} - -void SuplaDeviceClass::setServer(const char *server) { - setString( - Supla::Channel::reg_dev.ServerName, server, SUPLA_SERVER_NAME_MAXSIZE); -} - -void SuplaDeviceClass::onGetUserLocaltimeResult( - TSDC_UserLocalTimeResult *result) { - if (clock) { - clock->parseLocaltimeFromServer(result); - } -} - -void SuplaDeviceClass::addClock(Supla::Clock *_clock) { - Serial.println(F("Clock class added")); - clock = _clock; -} - -Supla::Clock *SuplaDeviceClass::getClock() { - return clock; -} - -SuplaDeviceClass SuplaDevice; +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include "SuplaDevice.h" +#include "supla-common/IEEE754tools.h" +#include "supla-common/log.h" +#include "supla-common/srpc.h" +#include "supla/channel.h" +#include "supla/element.h" +#include "supla/io.h" +#include "supla/storage/storage.h" +#include "supla/timer.h" + +void SuplaDeviceClass::status(int newStatus, const char *msg, bool alwaysLog) { + bool showLog = false; + if (currentStatus != newStatus && !(newStatus == STATUS_REGISTER_IN_PROGRESS && currentStatus > STATUS_REGISTER_IN_PROGRESS)) { + if (impl_arduino_status != NULL) { + impl_arduino_status(newStatus, msg); + } + currentStatus = newStatus; + showLog = true; + } + if (alwaysLog || showLog) supla_log(LOG_DEBUG, "Current status: [%d] %s", newStatus, msg); +} + +SuplaDeviceClass::SuplaDeviceClass() + : port(-1), + connectionFailCounter(0), + networkIsNotReadyCounter(0), + currentStatus(STATUS_UNKNOWN), + impl_arduino_status(nullptr), + clock(nullptr) { + srpc = NULL; + registered = 0; + lastIterateTime = 0; + waitForIterate = 0; +} + +SuplaDeviceClass::~SuplaDeviceClass() { +} + +void SuplaDeviceClass::setStatusFuncImpl( + _impl_arduino_status impl_arduino_status) { + this->impl_arduino_status = impl_arduino_status; +} + +bool SuplaDeviceClass::isInitialized(bool msg) { + if (srpc != NULL) { + if (msg) + status(STATUS_ALREADY_INITIALIZED, "SuplaDevice is already initialized"); + + return true; + } + + return false; +} + +bool SuplaDeviceClass::begin(char GUID[SUPLA_GUID_SIZE], + const char *Server, + const char *email, + char authkey[SUPLA_AUTHKEY_SIZE], + unsigned char version) { + setGUID(GUID); + setServer(Server); + setEmail(email); + setAuthKey(authkey); + + return begin(version); +} + +bool SuplaDeviceClass::begin(unsigned char version) { + if (isInitialized(true)) return false; + supla_log(LOG_DEBUG, "Supla - starting initialization"); + + Supla::Storage::Init(); + + // Supla::Storage::LoadDeviceConfig(); + // Supla::Storage::LoadElementConfig(); + + // Pefrorm dry run of write state to validate stored state section with + // current device configuration + if (Supla::Storage::PrepareState(true)) { + Serial.println(F( + "Validating storage state section with current device configuration")); + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onSaveState(); + delay(0); + } + // If state storage validation was successful, perform read state + if (Supla::Storage::FinalizeSaveState()) { + Serial.println( + F("Storage state section validation completed. Loading elements " + "state...")); + // Iterate all elements and load state + Supla::Storage::PrepareState(); + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onLoadState(); + delay(0); + } + } + } else { + Serial.println(F("Storage not found. Running without state memory")); + } + + // Initialize elements + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onInit(); + delay(0); + } + + // Enable timers + Supla::initTimers(); + + if (Supla::Network::Instance() == NULL) { + status(STATUS_MISSING_NETWORK_INTERFACE, "Network Interface not defined!"); + return false; + } + + bool emptyGuidDetected = true; + for (int i = 0; i < SUPLA_GUID_SIZE; i++) { + if (Supla::Channel::reg_dev.GUID[i] != 0) { + emptyGuidDetected = false; + } + } + if (emptyGuidDetected) { + status(STATUS_INVALID_GUID, "Missing GUID"); + return false; + } + + if (Supla::Channel::reg_dev.ServerName[0] == '\0') { + status(STATUS_UNKNOWN_SERVER_ADDRESS, "Missing server address"); + return false; + } + + if (Supla::Channel::reg_dev.Email[0] == '\0') { + status(STATUS_MISSING_CREDENTIALS, "Missing email address"); + return false; + } + + bool emptyAuthKeyDetected = true; + for (int i = 0; i < SUPLA_AUTHKEY_SIZE; i++) { + if (Supla::Channel::reg_dev.AuthKey[i] != 0) { + emptyAuthKeyDetected = false; + break; + } + } + if (emptyAuthKeyDetected) { + status(STATUS_INVALID_AUTHKEY, "Missing AuthKey"); + return false; + } + + if (strnlen(Supla::Channel::reg_dev.Name, SUPLA_DEVICE_NAME_MAXSIZE) == 0) { +#if defined(ARDUINO_ARCH_ESP8266) + setString( + Supla::Channel::reg_dev.Name, "ESP8266", SUPLA_DEVICE_NAME_MAXSIZE); +#elif defined(ARDUINO_ARCH_ESP32) + setString(Supla::Channel::reg_dev.Name, "ESP32", SUPLA_DEVICE_NAME_MAXSIZE); +#else + setString( + Supla::Channel::reg_dev.Name, "ARDUINO", SUPLA_DEVICE_NAME_MAXSIZE); +#endif + } + + if (strnlen(Supla::Channel::reg_dev.SoftVer, SUPLA_SOFTVER_MAXSIZE) == 0) { + setString(Supla::Channel::reg_dev.SoftVer, + "User SW, lib 2.3.5", + SUPLA_SOFTVER_MAXSIZE); + } + + Serial.println(F("Initializing network layer")); + Supla::Network::Setup(); + + TsrpcParams srpc_params; + srpc_params_init(&srpc_params); + srpc_params.data_read = &Supla::data_read; + srpc_params.data_write = &Supla::data_write; + srpc_params.on_remote_call_received = &Supla::message_received; + srpc_params.user_params = this; + + srpc = srpc_init(&srpc_params); + + // Set Supla protocol interface version + srpc_set_proto_version(srpc, version); + + supla_log(LOG_DEBUG, "Using Supla protocol version %d", version); + + status(STATUS_INITIALIZED, "SuplaDevice initialized"); + return true; +} + +void SuplaDeviceClass::setName(const char *Name) { + if (isInitialized(true)) return; + setString(Supla::Channel::reg_dev.Name, Name, SUPLA_DEVICE_NAME_MAXSIZE); +} + +void SuplaDeviceClass::setString(char *dst, const char *src, int max_size) { + if (src == NULL) { + dst[0] = 0; + return; + } + + int size = strlen(src); + + if (size + 1 > max_size) size = max_size - 1; + + memcpy(dst, src, size); +} + +void SuplaDeviceClass::onTimer(void) { + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onTimer(); + } +} + +void SuplaDeviceClass::onFastTimer(void) { + // Iteration over all impulse counters will count incomming impulses. It is + // after SuplaDevice initialization (because we have to read stored counter + // values) and before any other operation like connection to Supla cloud + // (because we want to count impulses even when we have connection issues. + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onFastTimer(); + } +} + +void SuplaDeviceClass::iterate(void) { + if (!isInitialized(false)) return; + + unsigned long _millis = millis(); + unsigned long timeDiff = _millis - lastIterateTime; + + uptime.iterate(_millis); + + // Iterate all elements + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->iterateAlways(); + delay(0); + } + + // Iterate all elements and saves state + if (Supla::Storage::SaveStateAllowed(_millis)) { + Supla::Storage::PrepareState(); + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onSaveState(); + delay(0); + } + Supla::Storage::FinalizeSaveState(); + } + + if (waitForIterate != 0 && _millis < waitForIterate) { + return; + } else { + waitForIterate = 0; + } + + // Restart network after >1 min of failed connection attempts + if (connectionFailCounter > 30) { + connectionFailCounter = 0; + supla_log(LOG_DEBUG, + "Connection fail counter overflow. Trying to setup network " + "interface again"); + Supla::Network::Setup(); + return; + } + + if (!Supla::Network::IsReady()) { + uptime.setConnectionLostCause( + SUPLA_LASTCONNECTIONRESETCAUSE_WIFI_CONNECTION_LOST); + waitForIterate = _millis + 100; + status(STATUS_NETWORK_DISCONNECTED, "No connection to network"); + networkIsNotReadyCounter++; + if (networkIsNotReadyCounter > 20) { + networkIsNotReadyCounter = 0; + connectionFailCounter++; + } + return; + } + networkIsNotReadyCounter = 0; + + if (!Supla::Network::Connected()) { + + uptime.setConnectionLostCause( + SUPLA_LASTCONNECTIONRESETCAUSE_SERVER_CONNECTION_LOST); + + registered = 0; + + int result = + Supla::Network::Connect(Supla::Channel::reg_dev.ServerName, port); + if (1 == result) { + uptime.resetConnectionUptime(); + connectionFailCounter = 0; + supla_log(LOG_DEBUG, "Connected to Supla Server"); + } else { + status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); + supla_log(LOG_DEBUG, + "Connection fail (%d). Server: %s", + result, + Supla::Channel::reg_dev.ServerName); + + Supla::Network::Disconnect(); + waitForIterate = _millis + 2000; + connectionFailCounter++; + return; + } + } + + Supla::Network::Iterate(); + + if (srpc_iterate(srpc) == SUPLA_RESULT_FALSE) { + status(STATUS_ITERATE_FAIL, "Iterate fail"); + Supla::Network::Disconnect(); + + waitForIterate = _millis + 5000; + return; + } + + if (registered == 0) { + // Perform registration if we are not yet registered + registered = -1; + lastIterateTime = _millis; + status(STATUS_REGISTER_IN_PROGRESS, "Register in progress"); + if (!srpc_ds_async_registerdevice_e(srpc, &Supla::Channel::reg_dev)) { + supla_log(LOG_DEBUG, "Fatal SRPC failure!"); + } + } else if (registered == -1) { + // Handle registration timeout (in case of no reply received) + if (timeDiff > 10*1000) { + supla_log(LOG_DEBUG, "No reply to registration message. Resetting connection."); + status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); + Supla::Network::Disconnect(); + + waitForIterate = _millis + 2000; + connectionFailCounter++; + } + + } else if (registered == 1) { + // Device is registered and everything is correct + + if (Supla::Network::Ping(srpc) == false) { + uptime.setConnectionLostCause( + SUPLA_LASTCONNECTIONRESETCAUSE_ACTIVITY_TIMEOUT); + supla_log(LOG_DEBUG, "TIMEOUT - lost connection with server"); + status(STATUS_SERVER_DISCONNECTED, "Not connected to Supla server"); + Supla::Network::Disconnect(); + } + + if (timeDiff > 0) { + // Iterate all elements + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + if (!element->iterateConnected(srpc)) { + break; + } + delay(0); + } + + lastIterateTime = _millis; + } + } +} + +void SuplaDeviceClass::onVersionError(TSDC_SuplaVersionError *version_error) { + status(STATUS_PROTOCOL_VERSION_ERROR, "Protocol version error"); + Serial.print(F("Protocol version error. Server min: ")); + Serial.print(version_error->server_version_min); + Serial.print(F("; Server version: ")); + Serial.println(version_error->server_version); + + Supla::Network::Disconnect(); + + waitForIterate = millis() + 5000; +} + +void SuplaDeviceClass::onRegisterResult( + TSD_SuplaRegisterDeviceResult *register_device_result) { + _supla_int_t activity_timeout = 0; + + switch (register_device_result->result_code) { + // OK scenario + case SUPLA_RESULTCODE_TRUE: + activity_timeout = register_device_result->activity_timeout; + Supla::Network::Instance()->setActivityTimeout(activity_timeout); + registered = 1; + supla_log(LOG_DEBUG, + "Device registered (activity timeout %d s, server version: %d, " + "server min version: %d)", + register_device_result->activity_timeout, + register_device_result->version, + register_device_result->version_min); + lastIterateTime = millis(); + status(STATUS_REGISTERED_AND_READY, "Registered and ready"); + + if (activity_timeout != ACTIVITY_TIMEOUT) { + supla_log( + LOG_DEBUG, "Changing activity timeout to %d", ACTIVITY_TIMEOUT); + TDCS_SuplaSetActivityTimeout at; + at.activity_timeout = ACTIVITY_TIMEOUT; + srpc_dcs_async_set_activity_timeout(srpc, &at); + } + + for (auto element = Supla::Element::begin(); element != nullptr; + element = element->next()) { + element->onRegistered(); + delay(0); + } + + return; + + // NOK scenarios + case SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE: + status(STATUS_TEMPORARILY_UNAVAILABLE, "Temporarily unavailable!", true); + break; + + case SUPLA_RESULTCODE_GUID_ERROR: + status(STATUS_INVALID_GUID, "Incorrect device GUID!", true); + break; + + case SUPLA_RESULTCODE_AUTHKEY_ERROR: + status(STATUS_INVALID_AUTHKEY, "Incorrect AuthKey!", true); + break; + + case SUPLA_RESULTCODE_BAD_CREDENTIALS: + status(STATUS_BAD_CREDENTIALS, "Bad credentials - incorrect AuthKey or email", true); + break; + + case SUPLA_RESULTCODE_REGISTRATION_DISABLED: + status(STATUS_REGISTRATION_DISABLED, "Registration disabled!", true); + break; + + case SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED: + status(STATUS_DEVICE_LIMIT_EXCEEDED, "Device limit exceeded!", true); + break; + + case SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE: + status(STATUS_NO_LOCATION_AVAILABLE, "No location available!", true); + break; + + case SUPLA_RESULTCODE_DEVICE_DISABLED: + status(STATUS_DEVICE_IS_DISABLED, "Device is disabled!", true); + break; + + case SUPLA_RESULTCODE_LOCATION_DISABLED: + status(STATUS_LOCATION_IS_DISABLED, "Location is disabled!", true); + break; + + case SUPLA_RESULTCODE_LOCATION_CONFLICT: + status(STATUS_LOCATION_CONFLICT, "Location conflict!", true); + break; + + case SUPLA_RESULTCODE_CHANNEL_CONFLICT: + status(STATUS_CHANNEL_CONFLICT, "Channel conflict!", true); + break; + + default: + status(STATUS_UNKNOWN_ERROR, "Unknown registration error", true); + supla_log(LOG_ERR, + "Register result code %i", + register_device_result->result_code); + break; + } + + Supla::Network::Disconnect(); + waitForIterate = millis() + 5000; +} + +void SuplaDeviceClass::channelSetActivityTimeoutResult( + TSDC_SuplaSetActivityTimeoutResult *result) { + Supla::Network::Instance()->setActivityTimeout(result->activity_timeout); + supla_log( + LOG_DEBUG, "Activity timeout set to %d s", result->activity_timeout); +} + +void SuplaDeviceClass::setServerPort(int value) { + port = value; +} + +void SuplaDeviceClass::setSwVersion(const char *swVersion) { + setString(Supla::Channel::reg_dev.SoftVer, swVersion, SUPLA_SOFTVER_MAXSIZE); +} + +int SuplaDeviceClass::getCurrentStatus() { + return currentStatus; +} + +void SuplaDeviceClass::fillStateData(TDSC_ChannelState &channelState) { + channelState.Fields |= SUPLA_CHANNELSTATE_FIELD_UPTIME | + SUPLA_CHANNELSTATE_FIELD_CONNECTIONUPTIME; + + channelState.Uptime = uptime.getUptime(); + channelState.ConnectionUptime = uptime.getConnectionUptime(); + if (uptime.getLastResetCause() > 0) { + channelState.Fields |= SUPLA_CHANNELSTATE_FIELD_LASTCONNECTIONRESETCAUSE; + channelState.LastConnectionResetCause = uptime.getLastResetCause(); + } +} + +void SuplaDeviceClass::setGUID(char GUID[SUPLA_GUID_SIZE]) { + memcpy(Supla::Channel::reg_dev.GUID, GUID, SUPLA_GUID_SIZE); +} + +void SuplaDeviceClass::setAuthKey(char authkey[SUPLA_AUTHKEY_SIZE]) { + memcpy(Supla::Channel::reg_dev.AuthKey, authkey, SUPLA_AUTHKEY_SIZE); +} + +void SuplaDeviceClass::setEmail(const char *email) { + setString(Supla::Channel::reg_dev.Email, email, SUPLA_EMAIL_MAXSIZE); +} + +void SuplaDeviceClass::setServer(const char *server) { + setString( + Supla::Channel::reg_dev.ServerName, server, SUPLA_SERVER_NAME_MAXSIZE); +} + +void SuplaDeviceClass::onGetUserLocaltimeResult( + TSDC_UserLocalTimeResult *result) { + if (clock) { + clock->parseLocaltimeFromServer(result); + } +} + +void SuplaDeviceClass::addClock(Supla::Clock *_clock) { + Serial.println(F("Clock class added")); + clock = _clock; +} + +Supla::Clock *SuplaDeviceClass::getClock() { + return clock; +} + +SuplaDeviceClass SuplaDevice; diff --git a/lib/SuplaDevice/src/SuplaDevice.h b/lib/SuplaDevice/src/SuplaDevice.h index 8841dbdc..ffe794b3 100644 --- a/lib/SuplaDevice/src/SuplaDevice.h +++ b/lib/SuplaDevice/src/SuplaDevice.h @@ -1,127 +1,127 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef SUPLADEVICE_H -#define SUPLADEVICE_H - -#include "supla-common/proto.h" -#include "supla/network/network.h" -#include "supla/uptime.h" -#include "supla/clock/clock.h" - -#define ACTIVITY_TIMEOUT 30 - -#define STATUS_UNKNOWN -1 -#define STATUS_ALREADY_INITIALIZED 1 -#define STATUS_MISSING_NETWORK_INTERFACE 2 -#define STATUS_UNKNOWN_SERVER_ADDRESS 3 -#define STATUS_UNKNOWN_LOCATION_ID 4 -#define STATUS_INITIALIZED 5 -#define STATUS_SERVER_DISCONNECTED 6 -#define STATUS_ITERATE_FAIL 7 -#define STATUS_NETWORK_DISCONNECTED 8 - -#define STATUS_REGISTER_IN_PROGRESS 10 // Don't change -#define STATUS_REGISTERED_AND_READY 17 // Don't change - -#define STATUS_TEMPORARILY_UNAVAILABLE 21 -#define STATUS_INVALID_GUID 22 -#define STATUS_CHANNEL_LIMIT_EXCEEDED 23 -#define STATUS_PROTOCOL_VERSION_ERROR 24 -#define STATUS_BAD_CREDENTIALS 25 -#define STATUS_LOCATION_CONFLICT 26 -#define STATUS_CHANNEL_CONFLICT 27 -#define STATUS_DEVICE_IS_DISABLED 28 -#define STATUS_LOCATION_IS_DISABLED 29 -#define STATUS_DEVICE_LIMIT_EXCEEDED 30 -#define STATUS_REGISTRATION_DISABLED 31 -#define STATUS_MISSING_CREDENTIALS 32 -#define STATUS_INVALID_AUTHKEY 33 -#define STATUS_NO_LOCATION_AVAILABLE 34 -#define STATUS_UNKNOWN_ERROR 35 - - -typedef void (*_impl_arduino_status)(int status, const char *msg); - -class SuplaDeviceClass { - protected: - void *srpc; - int8_t registered; - int port; - int connectionFailCounter; - int networkIsNotReadyCounter; - - unsigned long lastIterateTime; - unsigned long waitForIterate; - - int currentStatus; - - _impl_arduino_status impl_arduino_status; - - Supla::Uptime uptime; - Supla::Clock *clock; - - bool isInitialized(bool msg); - void setString(char *dst, const char *src, int max_size); - - private: - void status(int status, const char *msg, bool alwaysLog = false); - - public: - SuplaDeviceClass(); - ~SuplaDeviceClass(); - - void fillStateData(TDSC_ChannelState &channelState); - void addClock(Supla::Clock *clock); - Supla::Clock *getClock(); - - bool begin(char GUID[SUPLA_GUID_SIZE], - const char *Server, - const char *email, - char authkey[SUPLA_AUTHKEY_SIZE], - unsigned char version = 16); - - bool begin(unsigned char version = 16); - - // Use ASCII only in name - void setName(const char *Name); - - void setGUID(char GUID[SUPLA_GUID_SIZE]); - void setAuthKey(char authkey[SUPLA_AUTHKEY_SIZE]); - void setEmail(const char *email); - void setServer(const char *server); - - // Timer with 100 Hz frequency (10 ms) - void onTimer(void); - // TImer with 2000 Hz frequency (0.5 ms) - void onFastTimer(void); - void iterate(void); - - void setStatusFuncImpl(_impl_arduino_status impl_arduino_status); - void setServerPort(int value); - - void onVersionError(TSDC_SuplaVersionError *version_error); - void onRegisterResult(TSD_SuplaRegisterDeviceResult *register_device_result); - void channelSetActivityTimeoutResult( - TSDC_SuplaSetActivityTimeoutResult *result); - void onGetUserLocaltimeResult(TSDC_UserLocalTimeResult *result); - - void setSwVersion(const char *); - int getCurrentStatus(); -}; - -extern SuplaDeviceClass SuplaDevice; -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef SUPLADEVICE_H +#define SUPLADEVICE_H + +#include "supla-common/proto.h" +#include "supla/network/network.h" +#include "supla/uptime.h" +#include "supla/clock/clock.h" + +#define ACTIVITY_TIMEOUT 30 + +#define STATUS_UNKNOWN -1 +#define STATUS_ALREADY_INITIALIZED 1 +#define STATUS_MISSING_NETWORK_INTERFACE 2 +#define STATUS_UNKNOWN_SERVER_ADDRESS 3 +#define STATUS_UNKNOWN_LOCATION_ID 4 +#define STATUS_INITIALIZED 5 +#define STATUS_SERVER_DISCONNECTED 6 +#define STATUS_ITERATE_FAIL 7 +#define STATUS_NETWORK_DISCONNECTED 8 + +#define STATUS_REGISTER_IN_PROGRESS 10 // Don't change +#define STATUS_REGISTERED_AND_READY 17 // Don't change + +#define STATUS_TEMPORARILY_UNAVAILABLE 21 +#define STATUS_INVALID_GUID 22 +#define STATUS_CHANNEL_LIMIT_EXCEEDED 23 +#define STATUS_PROTOCOL_VERSION_ERROR 24 +#define STATUS_BAD_CREDENTIALS 25 +#define STATUS_LOCATION_CONFLICT 26 +#define STATUS_CHANNEL_CONFLICT 27 +#define STATUS_DEVICE_IS_DISABLED 28 +#define STATUS_LOCATION_IS_DISABLED 29 +#define STATUS_DEVICE_LIMIT_EXCEEDED 30 +#define STATUS_REGISTRATION_DISABLED 31 +#define STATUS_MISSING_CREDENTIALS 32 +#define STATUS_INVALID_AUTHKEY 33 +#define STATUS_NO_LOCATION_AVAILABLE 34 +#define STATUS_UNKNOWN_ERROR 35 + + +typedef void (*_impl_arduino_status)(int status, const char *msg); + +class SuplaDeviceClass { + protected: + void *srpc; + int8_t registered; + int port; + int connectionFailCounter; + int networkIsNotReadyCounter; + + unsigned long lastIterateTime; + unsigned long waitForIterate; + + int currentStatus; + + _impl_arduino_status impl_arduino_status; + + Supla::Uptime uptime; + Supla::Clock *clock; + + bool isInitialized(bool msg); + void setString(char *dst, const char *src, int max_size); + + private: + void status(int status, const char *msg, bool alwaysLog = false); + + public: + SuplaDeviceClass(); + ~SuplaDeviceClass(); + + void fillStateData(TDSC_ChannelState &channelState); + void addClock(Supla::Clock *clock); + Supla::Clock *getClock(); + + bool begin(char GUID[SUPLA_GUID_SIZE], + const char *Server, + const char *email, + char authkey[SUPLA_AUTHKEY_SIZE], + unsigned char version = 16); + + bool begin(unsigned char version = 16); + + // Use ASCII only in name + void setName(const char *Name); + + void setGUID(char GUID[SUPLA_GUID_SIZE]); + void setAuthKey(char authkey[SUPLA_AUTHKEY_SIZE]); + void setEmail(const char *email); + void setServer(const char *server); + + // Timer with 100 Hz frequency (10 ms) + void onTimer(void); + // TImer with 2000 Hz frequency (0.5 ms) + void onFastTimer(void); + void iterate(void); + + void setStatusFuncImpl(_impl_arduino_status impl_arduino_status); + void setServerPort(int value); + + void onVersionError(TSDC_SuplaVersionError *version_error); + void onRegisterResult(TSD_SuplaRegisterDeviceResult *register_device_result); + void channelSetActivityTimeoutResult( + TSDC_SuplaSetActivityTimeoutResult *result); + void onGetUserLocaltimeResult(TSDC_UserLocalTimeResult *result); + + void setSwVersion(const char *); + int getCurrentStatus(); +}; + +extern SuplaDeviceClass SuplaDevice; +#endif diff --git a/lib/SuplaDevice/src/supla-common/lck.c b/lib/SuplaDevice/src/supla-common/lck.c index 9cace6b7..f6dc6dc3 100644 --- a/lib/SuplaDevice/src/supla-common/lck.c +++ b/lib/SuplaDevice/src/supla-common/lck.c @@ -1,200 +1,200 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "lck.h" - -#ifdef __LCK_DEBUG -#include -#include - -#include "log.h" -#endif /*__LCK_DEBUG*/ - -#if defined(__AVR__) || defined(ARDUINO_ARCH_ESP8266) || \ - defined(ARDUINO_ARCH_ESP32) -#define __SINGLE_THREAD -#else - -#ifdef _WIN32 -#include -#else -#include -#include -#endif /*_WIN32*/ - -#endif // defined(__AVR__) || defined(ARDUINO_ARCH_ESP8266) - // || defined(ARDUINO_ARCH_ESP32) - -#include - -#define MUTEX_COUNT 4 - -#ifndef __SINGLE_THREAD - -typedef struct { -#ifdef _WIN32 - CRITICAL_SECTION critSec; -#else - pthread_mutex_t mutex; -#ifdef __LCK_DEBUG - - pthread_t thread; - int count; - int lineNumber; - char fileName[100]; - -#endif /*__LCK_DEBUG*/ -#endif /*_WIN32*/ -} TLckData; -#endif - -#ifdef __LCK_DEBUG -void *ptrs[500]; - -void LCK_ICACHE_FLASH lck_debug_init(void) { memset(ptrs, 0, sizeof(ptrs)); } - -void LCK_ICACHE_FLASH lck_debug_dump(void) { - supla_log(LOG_INFO, "LCK DEBUG DUMP\n"); - int a; - int n = sizeof(ptrs) / sizeof(void *); - TLckData *l = 0; - - for (a = 0; a < n; a++) { - if ((l = (TLckData *)ptrs[a]) != 0 && l->count != 0) { - supla_log(LOG_INFO, "%p:%p %s:%i count=%i\n", (void *)l, - (void *)l->thread, l->fileName, l->lineNumber, l->count); - } - } - - supla_log(LOG_INFO, "<<-----\n"); -} - -#endif /*__LCK_DEBUG*/ - -void *LCK_ICACHE_FLASH lck_init(void) { -#ifdef __SINGLE_THREAD - return NULL; -#else - TLckData *lck = malloc(sizeof(TLckData)); - - if (lck != NULL) { -#ifdef __LCK_DEBUG - memset(lck, 0, sizeof(TLckData)); - int a; - int n = sizeof(ptrs) / sizeof(void *); - for (a = 0; a < n; a++) { - if (ptrs[a] == 0) { - ptrs[a] = lck; - break; - } - } -#endif /*__LCK_DEBUG*/ - -#ifdef _WIN32 - InitializeCriticalSectionEx(&lck->critSec, 4000, - CRITICAL_SECTION_NO_DEBUG_INFO); -#else - - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&lck->mutex, &attr); - -#endif /*_WIN32*/ - } - - return lck; -#endif /*__SINGLE_THREAD*/ -} - -#ifdef __LCK_DEBUG - -void LCK_ICACHE_FLASH __lck_lock(void *lck, const char *file, int line) { - _lck_lock(lck); - - ((TLckData *)lck)->thread = pthread_self(); - ((TLckData *)lck)->count++; - if (((TLckData *)lck)->count == 1) { - snprintf(((TLckData *)lck)->fileName, sizeof(((TLckData *)lck)->fileName), - "%s", file); - ((TLckData *)lck)->lineNumber = line; - } -} - -void LCK_ICACHE_FLASH _lck_lock(void *lck) { -#else -void lck_lock(void *lck) { -#endif /*__LCK_DEBUG*/ -#ifndef __SINGLE_THREAD - if (lck != NULL) { -#ifdef _WIN32 - EnterCriticalSection(&((TLckData *)lck)->critSec); // NOLINT -#else - pthread_mutex_lock(&((TLckData *)lck)->mutex); // NOLINT -#endif /*_WIN32*/ - } - -#endif /*__SINGLE_THREAD*/ -} - -void LCK_ICACHE_FLASH lck_unlock(void *lck) { -#ifdef __LCK_DEBUG - ((TLckData *)lck)->count--; -#endif /*__LCK_DEBUG*/ -#ifndef __SINGLE_THREAD - if (lck != NULL) { -#ifdef _WIN32 - LeaveCriticalSection(&((TLckData *)lck)->critSec); // NOLINT -#else - pthread_mutex_unlock(&((TLckData *)lck)->mutex); // NOLINT -#endif /*_WIN32*/ - } - -#endif /*__SINGLE_THREAD*/ -} - -int LCK_ICACHE_FLASH lck_unlock_r(void *lck, int result) { -#ifndef __SINGLE_THREAD - lck_unlock(lck); -#endif /*__SINGLE_THREAD*/ - return result; -} - -void LCK_ICACHE_FLASH lck_free(void *lck) { -#ifdef __LCK_DEBUG - int a; - int n = sizeof(ptrs) / sizeof(void *); - for (a = 0; a < n; a++) { - if (ptrs[a] == lck) { - ptrs[a] = 0; - break; - } - } -#endif /*__LCK_DEBUG*/ - -#ifndef __SINGLE_THREAD - if (lck != NULL) { -#ifdef _WIN32 - DeleteCriticalSection(&((TLckData *)lck)->critSec); // NOLINT -#else - pthread_mutex_destroy(&((TLckData *)lck)->mutex); // NOLINT -#endif /*_WIN32*/ - free(lck); - } -#endif /*__SINGLE_THREAD*/ -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "lck.h" + +#ifdef __LCK_DEBUG +#include +#include + +#include "log.h" +#endif /*__LCK_DEBUG*/ + +#if defined(__AVR__) || defined(ARDUINO_ARCH_ESP8266) || \ + defined(ARDUINO_ARCH_ESP32) +#define __SINGLE_THREAD +#else + +#ifdef _WIN32 +#include +#else +#include +#include +#endif /*_WIN32*/ + +#endif // defined(__AVR__) || defined(ARDUINO_ARCH_ESP8266) + // || defined(ARDUINO_ARCH_ESP32) + +#include + +#define MUTEX_COUNT 4 + +#ifndef __SINGLE_THREAD + +typedef struct { +#ifdef _WIN32 + CRITICAL_SECTION critSec; +#else + pthread_mutex_t mutex; +#ifdef __LCK_DEBUG + + pthread_t thread; + int count; + int lineNumber; + char fileName[100]; + +#endif /*__LCK_DEBUG*/ +#endif /*_WIN32*/ +} TLckData; +#endif + +#ifdef __LCK_DEBUG +void *ptrs[500]; + +void LCK_ICACHE_FLASH lck_debug_init(void) { memset(ptrs, 0, sizeof(ptrs)); } + +void LCK_ICACHE_FLASH lck_debug_dump(void) { + supla_log(LOG_INFO, "LCK DEBUG DUMP\n"); + int a; + int n = sizeof(ptrs) / sizeof(void *); + TLckData *l = 0; + + for (a = 0; a < n; a++) { + if ((l = (TLckData *)ptrs[a]) != 0 && l->count != 0) { + supla_log(LOG_INFO, "%p:%p %s:%i count=%i\n", (void *)l, + (void *)l->thread, l->fileName, l->lineNumber, l->count); + } + } + + supla_log(LOG_INFO, "<<-----\n"); +} + +#endif /*__LCK_DEBUG*/ + +void *LCK_ICACHE_FLASH lck_init(void) { +#ifdef __SINGLE_THREAD + return NULL; +#else + TLckData *lck = malloc(sizeof(TLckData)); + + if (lck != NULL) { +#ifdef __LCK_DEBUG + memset(lck, 0, sizeof(TLckData)); + int a; + int n = sizeof(ptrs) / sizeof(void *); + for (a = 0; a < n; a++) { + if (ptrs[a] == 0) { + ptrs[a] = lck; + break; + } + } +#endif /*__LCK_DEBUG*/ + +#ifdef _WIN32 + InitializeCriticalSectionEx(&lck->critSec, 4000, + CRITICAL_SECTION_NO_DEBUG_INFO); +#else + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&lck->mutex, &attr); + +#endif /*_WIN32*/ + } + + return lck; +#endif /*__SINGLE_THREAD*/ +} + +#ifdef __LCK_DEBUG + +void LCK_ICACHE_FLASH __lck_lock(void *lck, const char *file, int line) { + _lck_lock(lck); + + ((TLckData *)lck)->thread = pthread_self(); + ((TLckData *)lck)->count++; + if (((TLckData *)lck)->count == 1) { + snprintf(((TLckData *)lck)->fileName, sizeof(((TLckData *)lck)->fileName), + "%s", file); + ((TLckData *)lck)->lineNumber = line; + } +} + +void LCK_ICACHE_FLASH _lck_lock(void *lck) { +#else +void lck_lock(void *lck) { +#endif /*__LCK_DEBUG*/ +#ifndef __SINGLE_THREAD + if (lck != NULL) { +#ifdef _WIN32 + EnterCriticalSection(&((TLckData *)lck)->critSec); // NOLINT +#else + pthread_mutex_lock(&((TLckData *)lck)->mutex); // NOLINT +#endif /*_WIN32*/ + } + +#endif /*__SINGLE_THREAD*/ +} + +void LCK_ICACHE_FLASH lck_unlock(void *lck) { +#ifdef __LCK_DEBUG + ((TLckData *)lck)->count--; +#endif /*__LCK_DEBUG*/ +#ifndef __SINGLE_THREAD + if (lck != NULL) { +#ifdef _WIN32 + LeaveCriticalSection(&((TLckData *)lck)->critSec); // NOLINT +#else + pthread_mutex_unlock(&((TLckData *)lck)->mutex); // NOLINT +#endif /*_WIN32*/ + } + +#endif /*__SINGLE_THREAD*/ +} + +int LCK_ICACHE_FLASH lck_unlock_r(void *lck, int result) { +#ifndef __SINGLE_THREAD + lck_unlock(lck); +#endif /*__SINGLE_THREAD*/ + return result; +} + +void LCK_ICACHE_FLASH lck_free(void *lck) { +#ifdef __LCK_DEBUG + int a; + int n = sizeof(ptrs) / sizeof(void *); + for (a = 0; a < n; a++) { + if (ptrs[a] == lck) { + ptrs[a] = 0; + break; + } + } +#endif /*__LCK_DEBUG*/ + +#ifndef __SINGLE_THREAD + if (lck != NULL) { +#ifdef _WIN32 + DeleteCriticalSection(&((TLckData *)lck)->critSec); // NOLINT +#else + pthread_mutex_destroy(&((TLckData *)lck)->mutex); // NOLINT +#endif /*_WIN32*/ + free(lck); + } +#endif /*__SINGLE_THREAD*/ +} diff --git a/lib/SuplaDevice/src/supla-common/lck.h b/lib/SuplaDevice/src/supla-common/lck.h index dfd02098..92f8afd6 100644 --- a/lib/SuplaDevice/src/supla-common/lck.h +++ b/lib/SuplaDevice/src/supla-common/lck.h @@ -1,63 +1,63 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef LCK_H_ -#define LCK_H_ - -#if defined(ESP8266) || defined(ESP32) -#include -#define LCK_ICACHE_FLASH ICACHE_FLASH_ATTR -#endif - -#if defined(ARDUINO) -#undef LCK_ICACHE_FLASH -#endif /*defined(ARDUINO)*/ - -#ifndef LCK_ICACHE_FLASH -#define LCK_ICACHE_FLASH -#endif /*LCK_ICACHE_FLASH*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __DEBUG -// #define __LCK_DEBUG -#endif - -#ifdef __LCK_DEBUG -#define lck_lock(ptr) __lck_lock(ptr, __FILE__, __LINE__) -void LCK_ICACHE_FLASH _lck_lock(void *lck); -void LCK_ICACHE_FLASH __lck_lock(void *lck, const char *file, int line); -void LCK_ICACHE_FLASH lck_debug_init(void); -void LCK_ICACHE_FLASH lck_debug_dump(void); -#else -void LCK_ICACHE_FLASH lck_lock(void *lck); -#endif /*__LCK_DEBUG*/ - -char LCK_ICACHE_FLASH lck_lock_with_timeout(void *lck, int timeout_sec); -void LCK_ICACHE_FLASH lck_unlock(void *lck); -int LCK_ICACHE_FLASH lck_unlock_r(void *lck, int result); -void *LCK_ICACHE_FLASH lck_init(void); -void LCK_ICACHE_FLASH lck_free(void *lck); - -#ifdef __cplusplus -} -#endif - -#endif /* LCK_H_ */ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef LCK_H_ +#define LCK_H_ + +#if defined(ESP8266) || defined(ESP32) +#include +#define LCK_ICACHE_FLASH ICACHE_FLASH_ATTR +#endif + +#if defined(ARDUINO) +#undef LCK_ICACHE_FLASH +#endif /*defined(ARDUINO)*/ + +#ifndef LCK_ICACHE_FLASH +#define LCK_ICACHE_FLASH +#endif /*LCK_ICACHE_FLASH*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __DEBUG +// #define __LCK_DEBUG +#endif + +#ifdef __LCK_DEBUG +#define lck_lock(ptr) __lck_lock(ptr, __FILE__, __LINE__) +void LCK_ICACHE_FLASH _lck_lock(void *lck); +void LCK_ICACHE_FLASH __lck_lock(void *lck, const char *file, int line); +void LCK_ICACHE_FLASH lck_debug_init(void); +void LCK_ICACHE_FLASH lck_debug_dump(void); +#else +void LCK_ICACHE_FLASH lck_lock(void *lck); +#endif /*__LCK_DEBUG*/ + +char LCK_ICACHE_FLASH lck_lock_with_timeout(void *lck, int timeout_sec); +void LCK_ICACHE_FLASH lck_unlock(void *lck); +int LCK_ICACHE_FLASH lck_unlock_r(void *lck, int result); +void *LCK_ICACHE_FLASH lck_init(void); +void LCK_ICACHE_FLASH lck_free(void *lck); + +#ifdef __cplusplus +} +#endif + +#endif /* LCK_H_ */ diff --git a/lib/SuplaDevice/src/supla-common/log.h b/lib/SuplaDevice/src/supla-common/log.h index ee422a8e..5db096e9 100644 --- a/lib/SuplaDevice/src/supla-common/log.h +++ b/lib/SuplaDevice/src/supla-common/log.h @@ -1,71 +1,71 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef suplalog_H_ -#define suplalog_H_ - -#if defined(ESP8266) || defined(ESP32) -#include -#define LOG_ICACHE_FLASH ICACHE_FLASH_ATTR -#endif - -#if defined(ARDUINO) -#undef LOG_ICACHE_FLASH -#endif /*defined(ARDUINO)*/ - -#ifndef LOG_ICACHE_FLASH -#define LOG_ICACHE_FLASH -#endif /*LOG_ICACHE_FLASH*/ - -#if defined(ESP8266) || defined(__AVR__) || defined(_WIN32) || defined(ESP32) - -#define LOG_EMERG 0 -#define LOG_ALERT 1 -#define LOG_CRIT 2 -#define LOG_ERR 3 -#define LOG_WARNING 4 -#define LOG_NOTICE 5 -#define LOG_INFO 6 -#define LOG_DEBUG 7 - -#else - -#include - -#endif // defined(ESP8266) || defined(__AVR__) - // || defined(_WIN32) || defined(ESP32) - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __LOG_CALLBACK -typedef int (*_supla_log_callback)(int __pri, const char *message); - -void LOG_ICACHE_FLASH supla_log_set_callback(_supla_log_callback callback); -#endif /*__LOG_CALLBACK*/ - -void LOG_ICACHE_FLASH supla_log(int __pri, const char *__fmt, ...); -void LOG_ICACHE_FLASH supla_write_state_file(const char *file, int __pri, - const char *__fmt, ...); - -#ifdef __cplusplus -} -#endif /*__cplusplus*/ - -#endif /* suplalog_H_ */ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef suplalog_H_ +#define suplalog_H_ + +#if defined(ESP8266) || defined(ESP32) +#include +#define LOG_ICACHE_FLASH ICACHE_FLASH_ATTR +#endif + +#if defined(ARDUINO) +#undef LOG_ICACHE_FLASH +#endif /*defined(ARDUINO)*/ + +#ifndef LOG_ICACHE_FLASH +#define LOG_ICACHE_FLASH +#endif /*LOG_ICACHE_FLASH*/ + +#if defined(ESP8266) || defined(__AVR__) || defined(_WIN32) || defined(ESP32) + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#else + +#include + +#endif // defined(ESP8266) || defined(__AVR__) + // || defined(_WIN32) || defined(ESP32) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __LOG_CALLBACK +typedef int (*_supla_log_callback)(int __pri, const char *message); + +void LOG_ICACHE_FLASH supla_log_set_callback(_supla_log_callback callback); +#endif /*__LOG_CALLBACK*/ + +void LOG_ICACHE_FLASH supla_log(int __pri, const char *__fmt, ...); +void LOG_ICACHE_FLASH supla_write_state_file(const char *file, int __pri, + const char *__fmt, ...); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /* suplalog_H_ */ diff --git a/lib/SuplaDevice/src/supla-common/proto.c b/lib/SuplaDevice/src/supla-common/proto.c index 701212a1..ba40ec52 100644 --- a/lib/SuplaDevice/src/supla-common/proto.c +++ b/lib/SuplaDevice/src/supla-common/proto.c @@ -1,410 +1,410 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "proto.h" -#include -#include -#include -#include "log.h" - -#if defined(ESP8266) || defined(ESP32) - -#if !defined(ARDUINO_ARCH_ESP32) -#include -#endif -#define BUFFER_MIN_SIZE 512 -#define BUFFER_MAX_SIZE 2048 - -#if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) -#include -#include "espmissingincludes.h" -#endif - -#elif defined(__AVR__) - -#define BUFFER_MIN_SIZE 32 -#define BUFFER_MAX_SIZE 1024 - -#endif /*ESP8266*/ - -#ifndef BUFFER_MIN_SIZE -#define BUFFER_MIN_SIZE 0 -#endif /*BUFFER_MIN_SIZE*/ - -#ifndef BUFFER_MAX_SIZE -#define BUFFER_MAX_SIZE 131072 -#endif /*BUFFER_MAX_SIZE*/ - -char sproto_tag[SUPLA_TAG_SIZE] = {'S', 'U', 'P', 'L', 'A'}; - -typedef struct { - unsigned char begin_tag; - unsigned _supla_int_t size; - unsigned _supla_int_t data_size; - - char *buffer; -} TSuplaProtoInBuffer; - -#ifndef SPROTO_WITHOUT_OUT_BUFFER -typedef struct { - unsigned _supla_int_t size; - unsigned _supla_int_t data_size; - - char *buffer; -} TSuplaProtoOutBuffer; -#endif - -typedef struct { - unsigned _supla_int_t next_rr_id; - unsigned char version; - TSuplaProtoInBuffer in; -#ifndef SPROTO_WITHOUT_OUT_BUFFER - TSuplaProtoOutBuffer out; -#endif -} TSuplaProtoData; - -void *sproto_init(void) { - TSuplaProtoData *spd = malloc(sizeof(TSuplaProtoData)); - if (spd) { - memset(spd, 0, sizeof(TSuplaProtoData)); - spd->version = SUPLA_PROTO_VERSION; - return (spd); - } - - return (NULL); -} - -void sproto_free(void *spd_ptr) { - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - if (spd != NULL) { - if (spd->in.buffer != NULL) free(spd->in.buffer); -#ifndef SPROTO_WITHOUT_OUT_BUFFER - if (spd->out.buffer != NULL) free(spd->out.buffer); -#endif - - free(spd); - } -} - -unsigned char PROTO_ICACHE_FLASH sproto_buffer_append( - void *spd_ptr, char **buffer, unsigned _supla_int_t *buffer_size, - unsigned _supla_int_t *buffer_data_size, char *data, - unsigned _supla_int_t data_size) { - unsigned _supla_int_t size = *buffer_size; - - if (size < BUFFER_MIN_SIZE) { - size = BUFFER_MIN_SIZE; - } - - if (data_size > size - (*buffer_data_size)) { - size += data_size - (size - (*buffer_data_size)); - } - - if (size >= BUFFER_MAX_SIZE) return (SUPLA_RESULT_BUFFER_OVERFLOW); - - if (size != (*buffer_size)) { - char *new_buffer = (char *)realloc(*buffer, size); - - if (size > 0 && new_buffer == NULL) { - return (SUPLA_RESULT_FALSE); - } - -#ifndef ESP8266 -#ifndef ESP32 -#ifndef __AVR__ - if (errno == ENOMEM) return (SUPLA_RESULT_FALSE); -#endif -#endif -#endif - - *buffer = new_buffer; - } - - memcpy(&(*buffer)[(*buffer_data_size)], data, data_size); - - (*buffer_size) = size; - (*buffer_data_size) += data_size; - - return (SUPLA_RESULT_TRUE); -} - -char PROTO_ICACHE_FLASH sproto_in_buffer_append( - void *spd_ptr, char *data, unsigned _supla_int_t data_size) { - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - return sproto_buffer_append(spd_ptr, &spd->in.buffer, &spd->in.size, - &spd->in.data_size, data, data_size); -} - -#ifndef SPROTO_WITHOUT_OUT_BUFFER -char PROTO_ICACHE_FLASH sproto_out_buffer_append(void *spd_ptr, - TSuplaDataPacket *sdp) { - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - unsigned _supla_int_t sdp_size = sizeof(TSuplaDataPacket); - unsigned _supla_int_t packet_size = - sdp_size - SUPLA_MAX_DATA_SIZE + sdp->data_size; - - if (packet_size > sdp_size) return SUPLA_RESULT_DATA_TOO_LARGE; - - if (SUPLA_RESULT_TRUE == - sproto_buffer_append(spd_ptr, &spd->out.buffer, &spd->out.size, - &spd->out.data_size, (char *)sdp, packet_size)) { - return sproto_buffer_append(spd_ptr, &spd->out.buffer, &spd->out.size, - &spd->out.data_size, sproto_tag, - SUPLA_TAG_SIZE); - } - - return (SUPLA_RESULT_FALSE); -} - -unsigned _supla_int_t PROTO_ICACHE_FLASH sproto_pop_out_data( - void *spd_ptr, char *buffer, unsigned _supla_int_t buffer_size) { - unsigned _supla_int_t a; - unsigned _supla_int_t b; - - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - - if (spd->out.data_size <= 0 || buffer_size == 0 || buffer == NULL) return (0); - - if (spd->out.data_size < buffer_size) buffer_size = spd->out.data_size; - - memcpy(buffer, spd->out.buffer, buffer_size); - - b = 0; - - for (a = buffer_size; a < spd->out.data_size; a++) { - spd->out.buffer[b] = spd->out.buffer[a]; - b++; - } - - spd->out.data_size -= buffer_size; - - if (spd->out.data_size < spd->out.size) { - b = spd->out.size; - - spd->out.size = spd->out.data_size; - if (spd->out.size < BUFFER_MIN_SIZE) spd->out.size = BUFFER_MIN_SIZE; - - if (b != spd->out.size) { - char *new_out_buffer = (char *)realloc(spd->out.buffer, spd->out.size); - - if (new_out_buffer == NULL && spd->out.size > 0) { - spd->out.size = b; - } else { - spd->out.buffer = new_out_buffer; - } - } - } - - return (buffer_size); -} -#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ - -char PROTO_ICACHE_FLASH sproto_out_dataexists(void *spd_ptr) { -#ifdef SPROTO_WITHOUT_OUT_BUFFER - return SUPLA_RESULT_FALSE; -#else - return ((TSuplaProtoData *)spd_ptr)->out.data_size > 0 ? SUPLA_RESULT_TRUE - : SUPLA_RESULT_FALSE; -#endif -} - -char PROTO_ICACHE_FLASH sproto_in_dataexists(void *spd_ptr) { - return ((TSuplaProtoData *)spd_ptr)->in.data_size > 0 ? SUPLA_RESULT_TRUE - : SUPLA_RESULT_FALSE; -} - -void PROTO_ICACHE_FLASH sproto_shrink_in_buffer(TSuplaProtoInBuffer *in, - unsigned _supla_int_t size) { - unsigned _supla_int_t old_size = in->size; - _supla_int_t a, b; - - in->begin_tag = 0; - - if (size > in->data_size) size = in->data_size; - - b = 0; - - for (a = size; a < in->data_size; a++) { - in->buffer[b] = in->buffer[a]; - b++; - } - - in->data_size -= size; - - if (in->data_size < in->size) { - in->size = in->data_size; - - if (in->size < BUFFER_MIN_SIZE) in->size = BUFFER_MIN_SIZE; - - if (old_size != in->size) { - char *new_in_buffer = (char *)realloc(in->buffer, in->size); - - if (new_in_buffer == NULL && in->size > 0) { - in->size = old_size; - } else { - in->buffer = new_in_buffer; - } - } - } -} - -char PROTO_ICACHE_FLASH sproto_pop_in_sdp(void *spd_ptr, - TSuplaDataPacket *sdp) { - unsigned _supla_int_t header_size; - TSuplaDataPacket *_sdp; - - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - - if (spd->in.begin_tag == 0 && spd->in.data_size >= SUPLA_TAG_SIZE) { - if (memcmp(spd->in.buffer, sproto_tag, SUPLA_TAG_SIZE) == 0) { - spd->in.begin_tag = 1; - } else { - sproto_shrink_in_buffer(&spd->in, spd->in.data_size); - return SUPLA_RESULT_DATA_ERROR; - } - } - - if (spd->in.begin_tag == 1) { - header_size = sizeof(TSuplaDataPacket) - SUPLA_MAX_DATA_SIZE; - if ((spd->in.data_size - SUPLA_TAG_SIZE) >= header_size) { - _sdp = (TSuplaDataPacket *)spd->in.buffer; - - if (_sdp->version > SUPLA_PROTO_VERSION || - _sdp->version < SUPLA_PROTO_VERSION_MIN) { - sdp->version = _sdp->version; - sproto_shrink_in_buffer(&spd->in, spd->in.data_size); - - return SUPLA_RESULT_VERSION_ERROR; - } - - if ((header_size + _sdp->data_size) > sizeof(TSuplaDataPacket)) { - sproto_shrink_in_buffer(&spd->in, spd->in.data_size); - return SUPLA_RESULT_DATA_ERROR; - } - - if ((header_size + _sdp->data_size + SUPLA_TAG_SIZE) > spd->in.data_size) - return SUPLA_RESULT_FALSE; - - if (header_size + _sdp->data_size >= spd->in.size || - memcmp(&spd->in.buffer[header_size + _sdp->data_size], sproto_tag, - SUPLA_TAG_SIZE) != 0) { - sproto_shrink_in_buffer(&spd->in, spd->in.data_size); - - return SUPLA_RESULT_DATA_ERROR; - } - - memcpy(sdp, spd->in.buffer, header_size + _sdp->data_size); - sproto_shrink_in_buffer(&spd->in, - header_size + _sdp->data_size + SUPLA_TAG_SIZE); - - return (SUPLA_RESULT_TRUE); - } - } - - return (SUPLA_RESULT_FALSE); -} - -void PROTO_ICACHE_FLASH sproto_set_version(void *spd_ptr, - unsigned char version) { - if (version >= SUPLA_PROTO_VERSION_MIN && version <= SUPLA_PROTO_VERSION) { - ((TSuplaProtoData *)spd_ptr)->version = version; - } else { - ((TSuplaProtoData *)spd_ptr)->version = SUPLA_PROTO_VERSION; - } -} - -unsigned char PROTO_ICACHE_FLASH sproto_get_version(void *spd_ptr) { - return ((TSuplaProtoData *)spd_ptr)->version; -} - -void sproto_sdp_init(void *spd_ptr, TSuplaDataPacket *sdp) { - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - - memset(sdp, 0, sizeof(TSuplaDataPacket)); - memcpy(sdp->tag, sproto_tag, SUPLA_TAG_SIZE); - - spd->next_rr_id++; - - if (spd->next_rr_id == 0) spd->next_rr_id++; - - sdp->rr_id = spd->next_rr_id; - sdp->version = spd->version; -} - -TSuplaDataPacket *PROTO_ICACHE_FLASH sproto_sdp_malloc(void *spd_ptr) { - TSuplaDataPacket *result = malloc(sizeof(TSuplaDataPacket)); - - if (result) sproto_sdp_init(spd_ptr, result); - - return result; -} - -void PROTO_ICACHE_FLASH sproto_sdp_free(TSuplaDataPacket *sdp) { free(sdp); } - -char PROTO_ICACHE_FLASH sproto_set_data(TSuplaDataPacket *sdp, char *data, - unsigned _supla_int_t data_size, - unsigned _supla_int_t call_type) { - if (data_size > SUPLA_MAX_DATA_SIZE || (data_size > 0 && data == 0)) - return SUPLA_RESULT_FALSE; - - if (data_size > 0) memcpy(sdp->data, data, data_size); - - sdp->data_size = data_size; - sdp->call_type = call_type; - return SUPLA_RESULT_TRUE; -} - -void PROTO_ICACHE_FLASH sproto_log_summary(void *spd_ptr) { - if (spd_ptr == NULL) { - supla_log(LOG_DEBUG, "SPROTO - Not initialized!"); - return; - } - - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - - supla_log(LOG_DEBUG, "BUFFER IN"); - supla_log(LOG_DEBUG, " size: %i", spd->in.size); - supla_log(LOG_DEBUG, " data_size: %i", spd->in.data_size); - supla_log(LOG_DEBUG, " begin_tag: %i", spd->in.begin_tag); -#ifndef SPROTO_WITHOUT_OUT_BUFFER - supla_log(LOG_DEBUG, "BUFFER OUT"); - supla_log(LOG_DEBUG, " size: %i", spd->out.size); - supla_log(LOG_DEBUG, " data_size: %i", spd->out.data_size); -#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ -} - -void PROTO_ICACHE_FLASH sproto_buffer_dump(void *spd_ptr, unsigned char in) { - _supla_int_t a; - char *buffer = NULL; - _supla_int_t size = 0; - - TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; - - if (in != 0) { - buffer = spd->in.buffer; - size = spd->in.data_size; -#ifndef SPROTO_WITHOUT_OUT_BUFFER - } else { - buffer = spd->out.buffer; - size = spd->out.data_size; -#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ - } - - for (a = 0; a < size; a++) - supla_log(LOG_DEBUG, "%c [%i]", buffer[a], buffer[a]); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "proto.h" +#include +#include +#include +#include "log.h" + +#if defined(ESP8266) || defined(ESP32) + +#if !defined(ARDUINO_ARCH_ESP32) +#include +#endif +#define BUFFER_MIN_SIZE 512 +#define BUFFER_MAX_SIZE 2048 + +#if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) +#include +#include "espmissingincludes.h" +#endif + +#elif defined(__AVR__) + +#define BUFFER_MIN_SIZE 32 +#define BUFFER_MAX_SIZE 1024 + +#endif /*ESP8266*/ + +#ifndef BUFFER_MIN_SIZE +#define BUFFER_MIN_SIZE 0 +#endif /*BUFFER_MIN_SIZE*/ + +#ifndef BUFFER_MAX_SIZE +#define BUFFER_MAX_SIZE 131072 +#endif /*BUFFER_MAX_SIZE*/ + +char sproto_tag[SUPLA_TAG_SIZE] = {'S', 'U', 'P', 'L', 'A'}; + +typedef struct { + unsigned char begin_tag; + unsigned _supla_int_t size; + unsigned _supla_int_t data_size; + + char *buffer; +} TSuplaProtoInBuffer; + +#ifndef SPROTO_WITHOUT_OUT_BUFFER +typedef struct { + unsigned _supla_int_t size; + unsigned _supla_int_t data_size; + + char *buffer; +} TSuplaProtoOutBuffer; +#endif + +typedef struct { + unsigned _supla_int_t next_rr_id; + unsigned char version; + TSuplaProtoInBuffer in; +#ifndef SPROTO_WITHOUT_OUT_BUFFER + TSuplaProtoOutBuffer out; +#endif +} TSuplaProtoData; + +void *sproto_init(void) { + TSuplaProtoData *spd = malloc(sizeof(TSuplaProtoData)); + if (spd) { + memset(spd, 0, sizeof(TSuplaProtoData)); + spd->version = SUPLA_PROTO_VERSION; + return (spd); + } + + return (NULL); +} + +void sproto_free(void *spd_ptr) { + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + if (spd != NULL) { + if (spd->in.buffer != NULL) free(spd->in.buffer); +#ifndef SPROTO_WITHOUT_OUT_BUFFER + if (spd->out.buffer != NULL) free(spd->out.buffer); +#endif + + free(spd); + } +} + +unsigned char PROTO_ICACHE_FLASH sproto_buffer_append( + void *spd_ptr, char **buffer, unsigned _supla_int_t *buffer_size, + unsigned _supla_int_t *buffer_data_size, char *data, + unsigned _supla_int_t data_size) { + unsigned _supla_int_t size = *buffer_size; + + if (size < BUFFER_MIN_SIZE) { + size = BUFFER_MIN_SIZE; + } + + if (data_size > size - (*buffer_data_size)) { + size += data_size - (size - (*buffer_data_size)); + } + + if (size >= BUFFER_MAX_SIZE) return (SUPLA_RESULT_BUFFER_OVERFLOW); + + if (size != (*buffer_size)) { + char *new_buffer = (char *)realloc(*buffer, size); + + if (size > 0 && new_buffer == NULL) { + return (SUPLA_RESULT_FALSE); + } + +#ifndef ESP8266 +#ifndef ESP32 +#ifndef __AVR__ + if (errno == ENOMEM) return (SUPLA_RESULT_FALSE); +#endif +#endif +#endif + + *buffer = new_buffer; + } + + memcpy(&(*buffer)[(*buffer_data_size)], data, data_size); + + (*buffer_size) = size; + (*buffer_data_size) += data_size; + + return (SUPLA_RESULT_TRUE); +} + +char PROTO_ICACHE_FLASH sproto_in_buffer_append( + void *spd_ptr, char *data, unsigned _supla_int_t data_size) { + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + return sproto_buffer_append(spd_ptr, &spd->in.buffer, &spd->in.size, + &spd->in.data_size, data, data_size); +} + +#ifndef SPROTO_WITHOUT_OUT_BUFFER +char PROTO_ICACHE_FLASH sproto_out_buffer_append(void *spd_ptr, + TSuplaDataPacket *sdp) { + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + unsigned _supla_int_t sdp_size = sizeof(TSuplaDataPacket); + unsigned _supla_int_t packet_size = + sdp_size - SUPLA_MAX_DATA_SIZE + sdp->data_size; + + if (packet_size > sdp_size) return SUPLA_RESULT_DATA_TOO_LARGE; + + if (SUPLA_RESULT_TRUE == + sproto_buffer_append(spd_ptr, &spd->out.buffer, &spd->out.size, + &spd->out.data_size, (char *)sdp, packet_size)) { + return sproto_buffer_append(spd_ptr, &spd->out.buffer, &spd->out.size, + &spd->out.data_size, sproto_tag, + SUPLA_TAG_SIZE); + } + + return (SUPLA_RESULT_FALSE); +} + +unsigned _supla_int_t PROTO_ICACHE_FLASH sproto_pop_out_data( + void *spd_ptr, char *buffer, unsigned _supla_int_t buffer_size) { + unsigned _supla_int_t a; + unsigned _supla_int_t b; + + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + + if (spd->out.data_size <= 0 || buffer_size == 0 || buffer == NULL) return (0); + + if (spd->out.data_size < buffer_size) buffer_size = spd->out.data_size; + + memcpy(buffer, spd->out.buffer, buffer_size); + + b = 0; + + for (a = buffer_size; a < spd->out.data_size; a++) { + spd->out.buffer[b] = spd->out.buffer[a]; + b++; + } + + spd->out.data_size -= buffer_size; + + if (spd->out.data_size < spd->out.size) { + b = spd->out.size; + + spd->out.size = spd->out.data_size; + if (spd->out.size < BUFFER_MIN_SIZE) spd->out.size = BUFFER_MIN_SIZE; + + if (b != spd->out.size) { + char *new_out_buffer = (char *)realloc(spd->out.buffer, spd->out.size); + + if (new_out_buffer == NULL && spd->out.size > 0) { + spd->out.size = b; + } else { + spd->out.buffer = new_out_buffer; + } + } + } + + return (buffer_size); +} +#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ + +char PROTO_ICACHE_FLASH sproto_out_dataexists(void *spd_ptr) { +#ifdef SPROTO_WITHOUT_OUT_BUFFER + return SUPLA_RESULT_FALSE; +#else + return ((TSuplaProtoData *)spd_ptr)->out.data_size > 0 ? SUPLA_RESULT_TRUE + : SUPLA_RESULT_FALSE; +#endif +} + +char PROTO_ICACHE_FLASH sproto_in_dataexists(void *spd_ptr) { + return ((TSuplaProtoData *)spd_ptr)->in.data_size > 0 ? SUPLA_RESULT_TRUE + : SUPLA_RESULT_FALSE; +} + +void PROTO_ICACHE_FLASH sproto_shrink_in_buffer(TSuplaProtoInBuffer *in, + unsigned _supla_int_t size) { + unsigned _supla_int_t old_size = in->size; + _supla_int_t a, b; + + in->begin_tag = 0; + + if (size > in->data_size) size = in->data_size; + + b = 0; + + for (a = size; a < in->data_size; a++) { + in->buffer[b] = in->buffer[a]; + b++; + } + + in->data_size -= size; + + if (in->data_size < in->size) { + in->size = in->data_size; + + if (in->size < BUFFER_MIN_SIZE) in->size = BUFFER_MIN_SIZE; + + if (old_size != in->size) { + char *new_in_buffer = (char *)realloc(in->buffer, in->size); + + if (new_in_buffer == NULL && in->size > 0) { + in->size = old_size; + } else { + in->buffer = new_in_buffer; + } + } + } +} + +char PROTO_ICACHE_FLASH sproto_pop_in_sdp(void *spd_ptr, + TSuplaDataPacket *sdp) { + unsigned _supla_int_t header_size; + TSuplaDataPacket *_sdp; + + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + + if (spd->in.begin_tag == 0 && spd->in.data_size >= SUPLA_TAG_SIZE) { + if (memcmp(spd->in.buffer, sproto_tag, SUPLA_TAG_SIZE) == 0) { + spd->in.begin_tag = 1; + } else { + sproto_shrink_in_buffer(&spd->in, spd->in.data_size); + return SUPLA_RESULT_DATA_ERROR; + } + } + + if (spd->in.begin_tag == 1) { + header_size = sizeof(TSuplaDataPacket) - SUPLA_MAX_DATA_SIZE; + if ((spd->in.data_size - SUPLA_TAG_SIZE) >= header_size) { + _sdp = (TSuplaDataPacket *)spd->in.buffer; + + if (_sdp->version > SUPLA_PROTO_VERSION || + _sdp->version < SUPLA_PROTO_VERSION_MIN) { + sdp->version = _sdp->version; + sproto_shrink_in_buffer(&spd->in, spd->in.data_size); + + return SUPLA_RESULT_VERSION_ERROR; + } + + if ((header_size + _sdp->data_size) > sizeof(TSuplaDataPacket)) { + sproto_shrink_in_buffer(&spd->in, spd->in.data_size); + return SUPLA_RESULT_DATA_ERROR; + } + + if ((header_size + _sdp->data_size + SUPLA_TAG_SIZE) > spd->in.data_size) + return SUPLA_RESULT_FALSE; + + if (header_size + _sdp->data_size >= spd->in.size || + memcmp(&spd->in.buffer[header_size + _sdp->data_size], sproto_tag, + SUPLA_TAG_SIZE) != 0) { + sproto_shrink_in_buffer(&spd->in, spd->in.data_size); + + return SUPLA_RESULT_DATA_ERROR; + } + + memcpy(sdp, spd->in.buffer, header_size + _sdp->data_size); + sproto_shrink_in_buffer(&spd->in, + header_size + _sdp->data_size + SUPLA_TAG_SIZE); + + return (SUPLA_RESULT_TRUE); + } + } + + return (SUPLA_RESULT_FALSE); +} + +void PROTO_ICACHE_FLASH sproto_set_version(void *spd_ptr, + unsigned char version) { + if (version >= SUPLA_PROTO_VERSION_MIN && version <= SUPLA_PROTO_VERSION) { + ((TSuplaProtoData *)spd_ptr)->version = version; + } else { + ((TSuplaProtoData *)spd_ptr)->version = SUPLA_PROTO_VERSION; + } +} + +unsigned char PROTO_ICACHE_FLASH sproto_get_version(void *spd_ptr) { + return ((TSuplaProtoData *)spd_ptr)->version; +} + +void sproto_sdp_init(void *spd_ptr, TSuplaDataPacket *sdp) { + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + + memset(sdp, 0, sizeof(TSuplaDataPacket)); + memcpy(sdp->tag, sproto_tag, SUPLA_TAG_SIZE); + + spd->next_rr_id++; + + if (spd->next_rr_id == 0) spd->next_rr_id++; + + sdp->rr_id = spd->next_rr_id; + sdp->version = spd->version; +} + +TSuplaDataPacket *PROTO_ICACHE_FLASH sproto_sdp_malloc(void *spd_ptr) { + TSuplaDataPacket *result = malloc(sizeof(TSuplaDataPacket)); + + if (result) sproto_sdp_init(spd_ptr, result); + + return result; +} + +void PROTO_ICACHE_FLASH sproto_sdp_free(TSuplaDataPacket *sdp) { free(sdp); } + +char PROTO_ICACHE_FLASH sproto_set_data(TSuplaDataPacket *sdp, char *data, + unsigned _supla_int_t data_size, + unsigned _supla_int_t call_type) { + if (data_size > SUPLA_MAX_DATA_SIZE || (data_size > 0 && data == 0)) + return SUPLA_RESULT_FALSE; + + if (data_size > 0) memcpy(sdp->data, data, data_size); + + sdp->data_size = data_size; + sdp->call_type = call_type; + return SUPLA_RESULT_TRUE; +} + +void PROTO_ICACHE_FLASH sproto_log_summary(void *spd_ptr) { + if (spd_ptr == NULL) { + supla_log(LOG_DEBUG, "SPROTO - Not initialized!"); + return; + } + + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + + supla_log(LOG_DEBUG, "BUFFER IN"); + supla_log(LOG_DEBUG, " size: %i", spd->in.size); + supla_log(LOG_DEBUG, " data_size: %i", spd->in.data_size); + supla_log(LOG_DEBUG, " begin_tag: %i", spd->in.begin_tag); +#ifndef SPROTO_WITHOUT_OUT_BUFFER + supla_log(LOG_DEBUG, "BUFFER OUT"); + supla_log(LOG_DEBUG, " size: %i", spd->out.size); + supla_log(LOG_DEBUG, " data_size: %i", spd->out.data_size); +#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ +} + +void PROTO_ICACHE_FLASH sproto_buffer_dump(void *spd_ptr, unsigned char in) { + _supla_int_t a; + char *buffer = NULL; + _supla_int_t size = 0; + + TSuplaProtoData *spd = (TSuplaProtoData *)spd_ptr; + + if (in != 0) { + buffer = spd->in.buffer; + size = spd->in.data_size; +#ifndef SPROTO_WITHOUT_OUT_BUFFER + } else { + buffer = spd->out.buffer; + size = spd->out.data_size; +#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ + } + + for (a = 0; a < size; a++) + supla_log(LOG_DEBUG, "%c [%i]", buffer[a], buffer[a]); +} diff --git a/lib/SuplaDevice/src/supla-common/proto.h b/lib/SuplaDevice/src/supla-common/proto.h index ca3c7cf3..d73183ed 100644 --- a/lib/SuplaDevice/src/supla-common/proto.h +++ b/lib/SuplaDevice/src/supla-common/proto.h @@ -1,1911 +1,1911 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef supla_proto_H_ -#define supla_proto_H_ - -#ifdef _WIN32 - -#include -#define _supla_int_t int -#define _supla_int16_t short -#define _supla_int64_t __int64 -#define _supla_timeval timeval - -#elif defined(__AVR__) - -#define SPROTO_WITHOUT_OUT_BUFFER - -struct _supla_timeval { - long tv_sec[2]; - long tv_usec[2]; -}; - -#define timeval _supla_timeval - -#define _supla_int16_t int -#define _supla_int_t long -#define _supla_int64_t long long - -#elif defined(ESP8266) || defined(ESP32) -#include -#define PROTO_ICACHE_FLASH ICACHE_FLASH_ATTR - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#define SPROTO_WITHOUT_OUT_BUFFER -#endif /*ARDUINO_ARCH_ESP8266*/ - -struct _supla_timeval { - long long tv_sec; - long long tv_usec; -}; - -#define _supla_int16_t short -#define _supla_int_t int -#define _supla_int64_t long long -#elif defined(__arm__) - -struct _supla_timeval { - long long tv_sec; - long long tv_usec; -}; - -#include -#define _supla_int16_t short -#define _supla_int_t int -#define _supla_int64_t long long - -#else /*__arm__*/ -#include -#define _supla_int16_t short -#define _supla_int_t int -#define _supla_int64_t long long -#define _supla_timeval timeval -#endif - -#if defined(ARDUINO) -#undef PROTO_ICACHE_FLASH -#endif /*defined(ARDUINO)*/ - -#ifndef PROTO_ICACHE_FLASH -#define PROTO_ICACHE_FLASH -#endif /*PROTO_ICACHE_FLASH*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SUPLA_TAG_SIZE 5 -extern char sproto_tag[SUPLA_TAG_SIZE]; - -// DCS - device/client -> server -// SDC - server -> device/client -// DS - device -> server -// SD - server -> device -// CS - client -> server -// SC - server -> client - -#define SUPLA_PROTO_VERSION 17 -#define SUPLA_PROTO_VERSION_MIN 1 -#if defined(ARDUINO_ARCH_AVR) // Arduino IDE for Arduino HW -#define SUPLA_MAX_DATA_SIZE 1248 // Registration header + 32 channels x 21 B -#elif defined(ARDUINO_ARCH_ESP8266) || \ - defined(ARDUINO_ARCH_ESP32) // Arduino IDE for ESP8266 -#define SUPLA_MAX_DATA_SIZE 3264 // Registration header + 128 channels x 21 B -#elif defined(ESP8266) -#define SUPLA_MAX_DATA_SIZE 1536 -#else -#define SUPLA_MAX_DATA_SIZE 10240 -#endif -#define SUPLA_RC_MAX_DEV_COUNT 50 -#define SUPLA_SOFTVER_MAXSIZE 21 - -#define SUPLA_CAPTION_MAXSIZE 401 - -#define SUPLA_GUID_SIZE 16 -#define SUPLA_GUID_HEXSIZE 33 -#define SUPLA_LOCATION_PWD_MAXSIZE 33 -#define SUPLA_ACCESSID_PWD_MAXSIZE 33 -#define SUPLA_LOCATION_CAPTION_MAXSIZE SUPLA_CAPTION_MAXSIZE -#define SUPLA_LOCATIONPACK_MAXCOUNT 20 -#define SUPLA_CHANNEL_CAPTION_MAXSIZE SUPLA_CAPTION_MAXSIZE -#define SUPLA_CHANNELPACK_MAXCOUNT 20 -#define SUPLA_URL_HOST_MAXSIZE 101 -#define SUPLA_URL_PATH_MAXSIZE 101 -#define SUPLA_SERVER_NAME_MAXSIZE 65 -#define SUPLA_EMAIL_MAXSIZE 256 // ver. >= 7 -#define SUPLA_PASSWORD_MAXSIZE 64 // ver. >= 10 -#define SUPLA_AUTHKEY_SIZE 16 // ver. >= 7 -#define SUPLA_AUTHKEY_HEXSIZE 33 // ver. >= 7 -#define SUPLA_OAUTH_TOKEN_MAXSIZE 256 // ver. >= 10 -#define SUPLA_CHANNELGROUP_PACK_MAXCOUNT 20 // ver. >= 9 -#define SUPLA_CHANNELGROUP_CAPTION_MAXSIZE 401 // ver. >= 9 -#define SUPLA_CHANNELVALUE_PACK_MAXCOUNT 20 // ver. >= 9 -#define SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXCOUNT 5 // ver. >= 10 -#define SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE \ - (SUPLA_MAX_DATA_SIZE - 50) // ver. >= 10 -#define SUPLA_CALCFG_DATA_MAXSIZE 128 // ver. >= 10 -#define SUPLA_TIMEZONE_MAXSIZE 51 // ver. >= 11 - -#ifndef SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT -#define SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT 100 // ver. >= 9 -#endif /*SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT*/ - -#define SUPLA_DCS_CALL_GETVERSION 10 -#define SUPLA_SDC_CALL_GETVERSION_RESULT 20 -#define SUPLA_SDC_CALL_VERSIONERROR 30 -#define SUPLA_DCS_CALL_PING_SERVER 40 -#define SUPLA_SDC_CALL_PING_SERVER_RESULT 50 -#define SUPLA_DS_CALL_REGISTER_DEVICE 60 -#define SUPLA_DS_CALL_REGISTER_DEVICE_B 65 // ver. >= 2 -#define SUPLA_DS_CALL_REGISTER_DEVICE_C 67 // ver. >= 6 -#define SUPLA_DS_CALL_REGISTER_DEVICE_D 68 // ver. >= 7 -#define SUPLA_DS_CALL_REGISTER_DEVICE_E 69 // ver. >= 10 -#define SUPLA_SD_CALL_REGISTER_DEVICE_RESULT 70 -#define SUPLA_CS_CALL_REGISTER_CLIENT 80 -#define SUPLA_CS_CALL_REGISTER_CLIENT_B 85 // ver. >= 6 -#define SUPLA_CS_CALL_REGISTER_CLIENT_C 86 // ver. >= 7 -#define SUPLA_CS_CALL_REGISTER_CLIENT_D 87 // ver. >= 12 -#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT 90 -#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B 92 // ver. >= 9 -#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C 94 // ver. >= 17 -#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED 100 -#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B 102 // ver. >= 12 -#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C 103 // ver. >= 12 -#define SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED 105 // ver. >= 10 -#define SUPLA_SD_CALL_CHANNEL_SET_VALUE 110 -#define SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE 115 // ver. >= 13 -#define SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT 120 -#define SUPLA_SC_CALL_LOCATION_UPDATE 130 -#define SUPLA_SC_CALL_LOCATIONPACK_UPDATE 140 -#define SUPLA_SC_CALL_CHANNEL_UPDATE 150 -#define SUPLA_SC_CALL_CHANNELPACK_UPDATE 160 -#define SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE 170 -#define SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B 171 -#define SUPLA_CS_CALL_GET_NEXT 180 -#define SUPLA_SC_CALL_EVENT 190 -#define SUPLA_CS_CALL_CHANNEL_SET_VALUE 200 -#define SUPLA_CS_CALL_CHANNEL_SET_VALUE_B 205 // ver. >= 3 -#define SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT 210 // ver. >= 2 -#define SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT 220 // ver. >= 2 -#define SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL 300 // ver. >= 5 -#define SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT 310 // ver. >= 5 -#define SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED 320 // ver. >= 7 -#define SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT 330 // ver. >= 7 -#define SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST 340 // ver. >= 10 -#define SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT 350 // ver. >= 10 -#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_B 360 // ver. >= 8 -#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_C 361 // ver. >= 10 -#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_D 362 // ver. >= 15 -#define SUPLA_SC_CALL_CHANNEL_UPDATE_B 370 // ver. >= 8 -#define SUPLA_SC_CALL_CHANNEL_UPDATE_C 371 // ver. >= 10 -#define SUPLA_SC_CALL_CHANNEL_UPDATE_D 372 // ver. >= 15 -#define SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE 380 // ver. >= 9 -#define SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B 381 // ver. >= 10 -#define SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE 390 // ver. >= 9 -#define SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE 400 // ver. >= 9 -#define SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B 401 // ver. >= 15 -#define SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE 405 // ver. >= 10 -#define SUPLA_CS_CALL_SET_VALUE 410 // ver. >= 9 -#define SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST 420 // ver. >= 10 -#define SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT 425 // ver. >= 12 -#define SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT 430 // ver. >= 10 -#define SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST 440 // ver. >= 10 -#define SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B 445 // ver. >= 11 -#define SUPLA_SC_CALL_DEVICE_CALCFG_RESULT 450 // ver. >= 10 -#define SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST 460 // ver. >= 10 -#define SUPLA_DS_CALL_DEVICE_CALCFG_RESULT 470 // ver. >= 10 -#define SUPLA_DCS_CALL_GET_USER_LOCALTIME 480 // ver. >= 11 -#define SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT 490 // ver. >= 11 -#define SUPLA_CSD_CALL_GET_CHANNEL_STATE 500 // ver. >= 12 -#define SUPLA_DSC_CALL_CHANNEL_STATE_RESULT 510 // ver. >= 12 -#define SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG 520 // ver. >= 12 -#define SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT 530 // ver. >= 12 -#define SUPLA_CS_CALL_SET_CHANNEL_FUNCTION 540 // ver. >= 12 -#define SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT 550 // ver. >= 12 -#define SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST 560 // ver. >= 12 -#define SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT 570 // ver. >= 12 -#define SUPLA_CS_CALL_SET_REGISTRATION_ENABLED 580 // ver. >= 12 -#define SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT 590 // ver. >= 12 -#define SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST 600 // ver. >= 12 -#define SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT 610 // ver. >= 12 -#define SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS 620 // ver. >= 12 -#define SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT 630 // ver. >= 12 -#define SUPLA_CS_CALL_SET_CHANNEL_CAPTION 640 // ver. >= 12 -#define SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT 650 // ver. >= 12 -#define SUPLA_CS_CALL_SET_LOCATION_CAPTION 645 // ver. >= 14 -#define SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT 655 // ver. >= 14 -#define SUPLA_DS_CALL_GET_CHANNEL_CONFIG 680 // ver. >= 16 -#define SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT 690 // ver. >= 16 -#define SUPLA_DS_CALL_ACTIONTRIGGER 700 // ver. >= 16 -#define SUPLA_CS_CALL_TIMER_ARM 800 // ver. >= 17 - -#define SUPLA_RESULT_CALL_NOT_ALLOWED -5 -#define SUPLA_RESULT_DATA_TOO_LARGE -4 -#define SUPLA_RESULT_BUFFER_OVERFLOW -3 -#define SUPLA_RESULT_DATA_ERROR -2 -#define SUPLA_RESULT_VERSION_ERROR -1 -#define SUPLA_RESULT_FALSE 0 -#define SUPLA_RESULT_TRUE 1 - -#define SUPLA_RESULTCODE_NONE 0 -#define SUPLA_RESULTCODE_UNSUPORTED 1 -#define SUPLA_RESULTCODE_FALSE 2 -#define SUPLA_RESULTCODE_TRUE 3 -#define SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE 4 -#define SUPLA_RESULTCODE_BAD_CREDENTIALS 5 -#define SUPLA_RESULTCODE_LOCATION_CONFLICT 6 -#define SUPLA_RESULTCODE_CHANNEL_CONFLICT 7 -#define SUPLA_RESULTCODE_DEVICE_DISABLED 8 -#define SUPLA_RESULTCODE_ACCESSID_DISABLED 9 -#define SUPLA_RESULTCODE_LOCATION_DISABLED 10 -#define SUPLA_RESULTCODE_CLIENT_DISABLED 11 -#define SUPLA_RESULTCODE_CLIENT_LIMITEXCEEDED 12 -#define SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED 13 -#define SUPLA_RESULTCODE_GUID_ERROR 14 -#define SUPLA_RESULTCODE_HOSTNOTFOUND 15 // ver. >= 5 -#define SUPLA_RESULTCODE_CANTCONNECTTOHOST 16 // ver. >= 5 -#define SUPLA_RESULTCODE_REGISTRATION_DISABLED 17 // ver. >= 7 -#define SUPLA_RESULTCODE_ACCESSID_NOT_ASSIGNED 18 // ver. >= 7 -#define SUPLA_RESULTCODE_AUTHKEY_ERROR 19 // ver. >= 7 -#define SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE 20 // ver. >= 7 -#define SUPLA_RESULTCODE_USER_CONFLICT 21 // Deprecated -#define SUPLA_RESULTCODE_UNAUTHORIZED 22 // ver. >= 10 -#define SUPLA_RESULTCODE_AUTHORIZED 23 // ver. >= 10 -#define SUPLA_RESULTCODE_NOT_ALLOWED 24 // ver. >= 12 -#define SUPLA_RESULTCODE_CHANNELNOTFOUND 25 // ver. >= 12 -#define SUPLA_RESULTCODE_UNKNOWN_ERROR 26 // ver. >= 12 -#define SUPLA_RESULTCODE_DENY_CHANNEL_BELONG_TO_GROUP 27 // ver. >= 12 -#define SUPLA_RESULTCODE_DENY_CHANNEL_HAS_SCHEDULE 28 // ver. >= 12 -#define SUPLA_RESULTCODE_DENY_CHANNEL_IS_ASSOCIETED_WITH_SCENE 29 // ver. >= 12 -#define SUPLA_RESULTCODE_DENY_CHANNEL_IS_ASSOCIETED_WITH_ACTION_TRIGGER \ - 30 // ver. >= 16 - -#define SUPLA_OAUTH_RESULTCODE_ERROR 0 // ver. >= 10 -#define SUPLA_OAUTH_RESULTCODE_SUCCESS 1 // ver. >= 10 -#define SUPLA_OAUTH_TEMPORARILY_UNAVAILABLE 2 // ver. >= 10 - -#define SUPLA_DEVICE_NAME_MAXSIZE 201 -#define SUPLA_CLIENT_NAME_MAXSIZE 201 -#define SUPLA_SENDER_NAME_MAXSIZE 201 - -#ifdef __AVR__ -#ifdef __AVR_ATmega2560__ -#define SUPLA_CHANNELMAXCOUNT 32 -#else -#define SUPLA_CHANNELMAXCOUNT 1 -#endif -#else -#define SUPLA_CHANNELMAXCOUNT 128 -#endif - -#define SUPLA_CHANNELVALUE_SIZE 8 - -#ifdef __AVR__ -#define SUPLA_CHANNELEXTENDEDVALUE_SIZE 256 -#else -#define SUPLA_CHANNELEXTENDEDVALUE_SIZE 1024 -#endif - -#define SUPLA_CHANNELTYPE_SENSORNO 1000 -#define SUPLA_CHANNELTYPE_SENSORNC 1010 // DEPRECATED -#define SUPLA_CHANNELTYPE_DISTANCESENSOR 1020 // ver. >= 5 -#define SUPLA_CHANNELTYPE_CALLBUTTON 1500 // ver. >= 4 -#define SUPLA_CHANNELTYPE_RELAYHFD4 2000 -#define SUPLA_CHANNELTYPE_RELAYG5LA1A 2010 -#define SUPLA_CHANNELTYPE_2XRELAYG5LA1A 2020 -#define SUPLA_CHANNELTYPE_RELAY 2900 -#define SUPLA_CHANNELTYPE_THERMOMETERDS18B20 3000 -#define SUPLA_CHANNELTYPE_DHT11 3010 // ver. >= 4 -#define SUPLA_CHANNELTYPE_DHT22 3020 // ver. >= 4 -#define SUPLA_CHANNELTYPE_DHT21 3022 // ver. >= 5 -#define SUPLA_CHANNELTYPE_AM2302 3030 // ver. >= 4 -#define SUPLA_CHANNELTYPE_AM2301 3032 // ver. >= 5 - -#define SUPLA_CHANNELTYPE_THERMOMETER 3034 // ver. >= 8 -#define SUPLA_CHANNELTYPE_HUMIDITYSENSOR 3036 // ver. >= 8 -#define SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR 3038 // ver. >= 8 -#define SUPLA_CHANNELTYPE_WINDSENSOR 3042 // ver. >= 8 -#define SUPLA_CHANNELTYPE_PRESSURESENSOR 3044 // ver. >= 8 -#define SUPLA_CHANNELTYPE_RAINSENSOR 3048 // ver. >= 8 -#define SUPLA_CHANNELTYPE_WEIGHTSENSOR 3050 // ver. >= 8 -#define SUPLA_CHANNELTYPE_WEATHER_STATION 3100 // ver. >= 8 - -#define SUPLA_CHANNELTYPE_DIMMER 4000 // ver. >= 4 -#define SUPLA_CHANNELTYPE_RGBLEDCONTROLLER 4010 // ver. >= 4 -#define SUPLA_CHANNELTYPE_DIMMERANDRGBLED 4020 // ver. >= 4 - -#define SUPLA_CHANNELTYPE_ELECTRICITY_METER 5000 // ver. >= 10 -#define SUPLA_CHANNELTYPE_IMPULSE_COUNTER 5010 // ver. >= 10 - -#define SUPLA_CHANNELTYPE_THERMOSTAT 6000 // ver. >= 11 -#define SUPLA_CHANNELTYPE_THERMOSTAT_HEATPOL_HOMEPLUS 6010 // ver. >= 11 - -#define SUPLA_CHANNELTYPE_VALVE_OPENCLOSE 7000 // ver. >= 12 -#define SUPLA_CHANNELTYPE_VALVE_PERCENTAGE 7010 // ver. >= 12 -#define SUPLA_CHANNELTYPE_BRIDGE 8000 // ver. >= 12 -#define SUPLA_CHANNELTYPE_GENERAL_PURPOSE_MEASUREMENT 9000 // ver. >= 12 -#define SUPLA_CHANNELTYPE_ENGINE 10000 // ver. >= 12 -#define SUPLA_CHANNELTYPE_ACTIONTRIGGER 11000 // ver. >= 16 -#define SUPLA_CHANNELTYPE_DIGIGLASS 12000 // ver. >= 12 - -#define SUPLA_CHANNELDRIVER_MCP23008 2 - -#define SUPLA_CHANNELFNC_NONE 0 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEGATEWAYLOCK 10 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEGATE 20 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEGARAGEDOOR 30 -#define SUPLA_CHANNELFNC_THERMOMETER 40 -#define SUPLA_CHANNELFNC_HUMIDITY 42 -#define SUPLA_CHANNELFNC_HUMIDITYANDTEMPERATURE 45 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_GATEWAY 50 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_GATE 60 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_GARAGEDOOR 70 -#define SUPLA_CHANNELFNC_NOLIQUIDSENSOR 80 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEDOORLOCK 90 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_DOOR 100 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEROLLERSHUTTER 110 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEROOFWINDOW 115 // ver. >= 13 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_ROLLERSHUTTER 120 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_ROOFWINDOW 125 // ver. >= 13 -#define SUPLA_CHANNELFNC_POWERSWITCH 130 -#define SUPLA_CHANNELFNC_LIGHTSWITCH 140 -#define SUPLA_CHANNELFNC_RING 150 -#define SUPLA_CHANNELFNC_ALARM 160 -#define SUPLA_CHANNELFNC_NOTIFICATION 170 -#define SUPLA_CHANNELFNC_DIMMER 180 -#define SUPLA_CHANNELFNC_RGBLIGHTING 190 -#define SUPLA_CHANNELFNC_DIMMERANDRGBLIGHTING 200 -#define SUPLA_CHANNELFNC_DEPTHSENSOR 210 // ver. >= 5 -#define SUPLA_CHANNELFNC_DISTANCESENSOR 220 // ver. >= 5 -#define SUPLA_CHANNELFNC_OPENINGSENSOR_WINDOW 230 // ver. >= 8 -#define SUPLA_CHANNELFNC_MAILSENSOR 240 // ver. >= 8 -#define SUPLA_CHANNELFNC_WINDSENSOR 250 // ver. >= 8 -#define SUPLA_CHANNELFNC_PRESSURESENSOR 260 // ver. >= 8 -#define SUPLA_CHANNELFNC_RAINSENSOR 270 // ver. >= 8 -#define SUPLA_CHANNELFNC_WEIGHTSENSOR 280 // ver. >= 8 -#define SUPLA_CHANNELFNC_WEATHER_STATION 290 // ver. >= 8 -#define SUPLA_CHANNELFNC_STAIRCASETIMER 300 // ver. >= 8 -#define SUPLA_CHANNELFNC_ELECTRICITY_METER 310 // ver. >= 10 -#define SUPLA_CHANNELFNC_IC_ELECTRICITY_METER 315 // ver. >= 12 -#define SUPLA_CHANNELFNC_IC_GAS_METER 320 // ver. >= 10 -#define SUPLA_CHANNELFNC_IC_WATER_METER 330 // ver. >= 10 -#define SUPLA_CHANNELFNC_IC_HEAT_METER 340 // ver. >= 10 -#define SUPLA_CHANNELFNC_THERMOSTAT 400 // ver. >= 11 -#define SUPLA_CHANNELFNC_THERMOSTAT_HEATPOL_HOMEPLUS 410 // ver. >= 11 -#define SUPLA_CHANNELFNC_VALVE_OPENCLOSE 500 // ver. >= 12 -#define SUPLA_CHANNELFNC_VALVE_PERCENTAGE 510 // ver. >= 12 -#define SUPLA_CHANNELFNC_GENERAL_PURPOSE_MEASUREMENT 520 // ver. >= 12 -#define SUPLA_CHANNELFNC_CONTROLLINGTHEENGINESPEED 600 // ver. >= 12 -#define SUPLA_CHANNELFNC_ACTIONTRIGGER 700 // ver. >= 16 -#define SUPLA_CHANNELFNC_DIGIGLASS_HORIZONTAL 800 // ver. >= 14 -#define SUPLA_CHANNELFNC_DIGIGLASS_VERTICAL 810 // ver. >= 14 - -#define SUPLA_BIT_FUNC_CONTROLLINGTHEGATEWAYLOCK 0x00000001 -#define SUPLA_BIT_FUNC_CONTROLLINGTHEGATE 0x00000002 -#define SUPLA_BIT_FUNC_CONTROLLINGTHEGARAGEDOOR 0x00000004 -#define SUPLA_BIT_FUNC_CONTROLLINGTHEDOORLOCK 0x00000008 -#define SUPLA_BIT_FUNC_CONTROLLINGTHEROLLERSHUTTER 0x00000010 -#define SUPLA_BIT_FUNC_POWERSWITCH 0x00000020 -#define SUPLA_BIT_FUNC_LIGHTSWITCH 0x00000040 -#define SUPLA_BIT_FUNC_STAIRCASETIMER 0x00000080 // ver. >= 8 -#define SUPLA_BIT_FUNC_THERMOMETER 0x00000100 // ver. >= 12 -#define SUPLA_BIT_FUNC_HUMIDITYANDTEMPERATURE 0x00000200 // ver. >= 12 -#define SUPLA_BIT_FUNC_HUMIDITY 0x00000400 // ver. >= 12 -#define SUPLA_BIT_FUNC_WINDSENSOR 0x00000800 // ver. >= 12 -#define SUPLA_BIT_FUNC_PRESSURESENSOR 0x00001000 // ver. >= 12 -#define SUPLA_BIT_FUNC_RAINSENSOR 0x00002000 // ver. >= 12 -#define SUPLA_BIT_FUNC_WEIGHTSENSOR 0x00004000 // ver. >= 12 -#define SUPLA_BIT_FUNC_CONTROLLINGTHEROOFWINDOW 0x00008000 // ver. >= 13 - -#define SUPLA_EVENT_CONTROLLINGTHEGATEWAYLOCK 10 -#define SUPLA_EVENT_CONTROLLINGTHEGATE 20 -#define SUPLA_EVENT_CONTROLLINGTHEGARAGEDOOR 30 -#define SUPLA_EVENT_CONTROLLINGTHEDOORLOCK 40 -#define SUPLA_EVENT_CONTROLLINGTHEROLLERSHUTTER 50 -#define SUPLA_EVENT_CONTROLLINGTHEROOFWINDOW 55 -#define SUPLA_EVENT_POWERONOFF 60 -#define SUPLA_EVENT_LIGHTONOFF 70 -#define SUPLA_EVENT_STAIRCASETIMERONOFF 80 // ver. >= 9 -#define SUPLA_EVENT_VALVEOPENCLOSE 90 // ver. >= 12 -#define SUPLA_EVENT_SET_BRIDGE_VALUE_FAILED 100 // ver. >= 12 - -#define SUPLA_URL_PROTO_HTTP 0x01 -#define SUPLA_URL_PROTO_HTTPS 0x02 - -#define SUPLA_PLATFORM_UNKNOWN 0 -#define SUPLA_PLATFORM_ESP8266 1 - -#define SUPLA_TARGET_CHANNEL 0 -#define SUPLA_TARGET_GROUP 1 -#define SUPLA_TARGET_IODEVICE 2 - -#define SUPLA_MFR_UNKNOWN 0 -#define SUPLA_MFR_ACSOFTWARE 1 -#define SUPLA_MFR_TRANSCOM 2 -#define SUPLA_MFR_LOGI 3 -#define SUPLA_MFR_ZAMEL 4 -#define SUPLA_MFR_NICE 5 -#define SUPLA_MFR_ITEAD 6 -#define SUPLA_MFR_DOYLETRATT 7 -#define SUPLA_MFR_HEATPOL 8 -#define SUPLA_MFR_FAKRO 9 -#define SUPLA_MFR_PEVEKO 10 -#define SUPLA_MFR_WEKTA 11 -#define SUPLA_MFR_STA_SYSTEM 12 -#define SUPLA_MFR_DGF 13 -#define SUPLA_MFR_COMELIT 14 - -#define SUPLA_CHANNEL_FLAG_ZWAVE_BRIDGE 0x0001 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_IR_BRIDGE 0x0002 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_RF_BRIDGE 0x0004 // ver. >= 12 -// Free bit for future use: 0x0008 -#define SUPLA_CHANNEL_FLAG_CHART_TYPE_BAR 0x0010 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_CHART_DS_TYPE_DIFFERENTAL 0x0020 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_CHART_INTERPOLATE_MEASUREMENTS 0x0040 // ver. >= 12 -// Free bits for future use: 0x0080, 0x0100, 0x0200, 0x0400, 0x0800 -#define SUPLA_CHANNEL_FLAG_RS_AUTO_CALIBRATION 0x1000 // ver. >= 15 -#define SUPLA_CHANNEL_FLAG_CALCFG_RESET_COUNTERS 0x2000 // ver. >= 15 -// Free bits for future use: 0x8000 -#define SUPLA_CHANNEL_FLAG_CALCFG_RECALIBRATE 0x4000 // ver. >= 15 -#define SUPLA_CHANNEL_FLAG_CHANNELSTATE 0x00010000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_PHASE1_UNSUPPORTED 0x00020000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_PHASE2_UNSUPPORTED 0x00040000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_PHASE3_UNSUPPORTED 0x00080000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_TIME_SETTING_NOT_AVAILABLE 0x00100000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_RSA_ENCRYPTED_PIN_REQUIRED 0x00200000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_OFFLINE_DURING_REGISTRATION 0x00400000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_ZIGBEE_BRIDGE 0x00800000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_COUNTDOWN_TIMER_SUPPORTED 0x01000000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_LIGHTSOURCELIFESPAN_SETTABLE \ - 0x02000000 // ver. >= 12 -#define SUPLA_CHANNEL_FLAG_POSSIBLE_SLEEP_MODE 0x04000000 // ver. >= 12 - -#pragma pack(push, 1) - -typedef struct { - char tag[SUPLA_TAG_SIZE]; - unsigned char version; - unsigned _supla_int_t rr_id; // Request/Response ID - unsigned _supla_int_t call_type; - unsigned _supla_int_t data_size; - char data[SUPLA_MAX_DATA_SIZE]; // Last variable in struct! -} TSuplaDataPacket; - -typedef struct { - // server -> device|client - unsigned char proto_version_min; - unsigned char proto_version; - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; -} TSDC_SuplaGetVersionResult; - -typedef struct { - // server -> device|client - unsigned char server_version_min; - unsigned char server_version; -} TSDC_SuplaVersionError; - -typedef struct { - // device|client -> server - struct _supla_timeval now; -} TDCS_SuplaPingServer; - -// Compatibility with ESP8266 -struct timeval_compat { - _supla_int_t tv_sec; - _supla_int_t tv_usec; -}; - -typedef struct { - // device|client -> server - struct timeval_compat now; -} TDCS_SuplaPingServer_COMPAT; - -typedef struct { - // server -> device|client - struct _supla_timeval now; -} TSDC_SuplaPingServerResult; - -typedef struct { - // device|client -> server - unsigned char activity_timeout; -} TDCS_SuplaSetActivityTimeout; - -typedef struct { - // server -> device|client - unsigned char activity_timeout; - unsigned char min; - unsigned char max; -} TSDC_SuplaSetActivityTimeoutResult; - -typedef struct { - char value[SUPLA_CHANNELVALUE_SIZE]; - char sub_value[SUPLA_CHANNELVALUE_SIZE]; // For example sensor value -} TSuplaChannelValue; - -typedef struct { - char value[SUPLA_CHANNELVALUE_SIZE]; - char sub_value[SUPLA_CHANNELVALUE_SIZE]; // For example sensor value - char sub_value_type; // SUBV_TYPE_ -} TSuplaChannelValue_B; - -#define SUBV_TYPE_NOT_SET_OR_OFFLINE 0 -#define SUBV_TYPE_SENSOR 1 -#define SUBV_TYPE_ELECTRICITY_MEASUREMENTS 2 -#define SUBV_TYPE_IC_MEASUREMENTS 3 - -#define EV_TYPE_NONE 0 -#ifdef USE_DEPRECATED_EMEV_V1 -#define EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1 10 -#endif /*USE_DEPRECATED_EMEV_V1*/ -#define EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2 12 -#define EV_TYPE_IMPULSE_COUNTER_DETAILS_V1 20 -#define EV_TYPE_THERMOSTAT_DETAILS_V1 30 -#define EV_TYPE_CHANNEL_STATE_V1 40 -#define EV_TYPE_TIMER_STATE_V1 50 -#define EV_TYPE_CHANNEL_AND_TIMER_STATE_V1 60 -#define EV_TYPE_MULTI_VALUE 100 - -#define CALCFG_TYPE_THERMOSTAT_DETAILS_V1 10 - -typedef struct { - char type; // EV_TYPE_ - unsigned _supla_int_t size; - char value[SUPLA_CHANNELEXTENDEDVALUE_SIZE]; // Last variable in struct! -} TSuplaChannelExtendedValue; // v. >= 10 - -typedef struct { - // server -> client - char EOL; // End Of List - _supla_int_t Id; - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_LOCATION_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaLocation; - -typedef struct { - // server -> client - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaLocation - items[SUPLA_LOCATIONPACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaLocationPack; - -typedef struct { - // device -> server - unsigned char Number; - _supla_int_t Type; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TDS_SuplaDeviceChannel; - -typedef struct { - // device -> server - - _supla_int_t LocationID; - char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - unsigned char channel_count; - TDS_SuplaDeviceChannel - channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! -} TDS_SuplaRegisterDevice; - -typedef struct { - // device -> server - - unsigned char Number; - _supla_int_t Type; - - _supla_int_t FuncList; - _supla_int_t Default; - - char value[SUPLA_CHANNELVALUE_SIZE]; -} TDS_SuplaDeviceChannel_B; // ver. >= 2 - -typedef struct { - unsigned char relatedChannelNumber; // ChannelNumber + 1. - unsigned _supla_int_t disablesLocalOperation; -} TActionTriggerProperties; - -typedef struct { - // device -> server - - unsigned char Number; - _supla_int_t Type; - - union { - _supla_int_t FuncList; - unsigned _supla_int_t ActionTriggerCaps; // ver. >= 16 - }; - - _supla_int_t Default; - _supla_int_t Flags; - - union { - char value[SUPLA_CHANNELVALUE_SIZE]; - TActionTriggerProperties actionTriggerProperties; // ver. >= 16 - }; -} TDS_SuplaDeviceChannel_C; // ver. >= 10 - -typedef struct { - // device -> server - - _supla_int_t LocationID; - char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - unsigned char channel_count; - TDS_SuplaDeviceChannel_B - channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! -} TDS_SuplaRegisterDevice_B; // ver. >= 2 - -typedef struct { - // device -> server - - _supla_int_t LocationID; - char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; - - unsigned char channel_count; - TDS_SuplaDeviceChannel_B - channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! -} TDS_SuplaRegisterDevice_C; // ver. >= 6 - -typedef struct { - // device -> server - - char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 - char AuthKey[SUPLA_AUTHKEY_SIZE]; - - char GUID[SUPLA_GUID_SIZE]; - - char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; - - unsigned char channel_count; - TDS_SuplaDeviceChannel_B - channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! -} TDS_SuplaRegisterDevice_D; // ver. >= 7 - -typedef struct { - // device -> server - - char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 - char AuthKey[SUPLA_AUTHKEY_SIZE]; - - char GUID[SUPLA_GUID_SIZE]; - - char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; - - _supla_int_t Flags; // SUPLA_DEVICE_FLAG_* - _supla_int16_t ManufacturerID; - _supla_int16_t ProductID; - - unsigned char channel_count; - TDS_SuplaDeviceChannel_C - channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! -} TDS_SuplaRegisterDevice_E; // ver. >= 10 - -typedef struct { - // server -> device - - _supla_int_t result_code; - unsigned char activity_timeout; - unsigned char version; - unsigned char version_min; -} TSD_SuplaRegisterDeviceResult; - -typedef struct { - // device -> server - - unsigned char ChannelNumber; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TDS_SuplaDeviceChannelValue; - -typedef struct { - // device -> server - - unsigned char ChannelNumber; - unsigned char Offline; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TDS_SuplaDeviceChannelValue_B; // v. >= 12 - -typedef struct { - // device -> server - - unsigned char ChannelNumber; - unsigned char Offline; - unsigned _supla_int_t ValidityTimeSec; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TDS_SuplaDeviceChannelValue_C; // v. >= 12 - -typedef struct { - // device -> server - - unsigned char ChannelNumber; - TSuplaChannelExtendedValue value; // Last variable in struct! -} TDS_SuplaDeviceChannelExtendedValue; // v. >= 10 - -typedef struct { - // server -> device - _supla_int_t SenderID; - unsigned char ChannelNumber; - unsigned _supla_int_t DurationMS; - - char value[SUPLA_CHANNELVALUE_SIZE]; -} TSD_SuplaChannelNewValue; - -typedef struct { - // server -> device - _supla_int_t SenderID; - _supla_int_t GroupID; - unsigned char EOL; // End Of List - unsigned char ChannelNumber; - unsigned _supla_int_t DurationMS; - - char value[SUPLA_CHANNELVALUE_SIZE]; -} TSD_SuplaChannelGroupNewValue; // v. >= 13 - -typedef struct { - // device -> server - unsigned char ChannelNumber; - _supla_int_t SenderID; - char Success; -} TDS_SuplaChannelNewValueResult; - -typedef struct { - // server -> client - - char EOL; // End Of List - _supla_int_t Id; - char online; - - TSuplaChannelValue value; -} TSC_SuplaChannelValue; - -typedef struct { - // server -> client - - char EOL; // End Of List - _supla_int_t Id; - char online; - - TSuplaChannelValue_B value; -} TSC_SuplaChannelValue_B; // ver. >= 15 - -typedef struct { - // server -> client - _supla_int_t Id; - - TSuplaChannelExtendedValue value; // Last variable in struct! -} TSC_SuplaChannelExtendedValue; - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - - TSC_SuplaChannelValue - items[SUPLA_CHANNELVALUE_PACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelValuePack; // ver. >= 9 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - - TSC_SuplaChannelValue_B - items[SUPLA_CHANNELVALUE_PACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelValuePack_B; // ver. >= 15 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - unsigned _supla_int_t pack_size; - - char pack[SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE]; // Last variable in - // struct! -} TSC_SuplaChannelExtendedValuePack; // ver. >= 10 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t LocationID; - _supla_int_t Func; - char online; - - TSuplaChannelValue value; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannel; - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannel - items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelPack; - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t LocationID; - _supla_int_t Func; - _supla_int_t AltIcon; - unsigned _supla_int_t Flags; - unsigned char ProtocolVersion; - char online; - - TSuplaChannelValue value; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannel_B; // ver. >= 8 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannel_B - items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelPack_B; // ver. >= 8 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t DeviceID; - _supla_int_t LocationID; - _supla_int_t Type; - _supla_int_t Func; - _supla_int_t AltIcon; - _supla_int_t UserIcon; - _supla_int16_t ManufacturerID; - _supla_int16_t ProductID; - - unsigned _supla_int_t Flags; - unsigned char ProtocolVersion; - char online; - - TSuplaChannelValue value; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannel_C; // ver. >= 10 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t DeviceID; - _supla_int_t LocationID; - _supla_int_t Type; - _supla_int_t Func; - _supla_int_t AltIcon; - _supla_int_t UserIcon; - _supla_int16_t ManufacturerID; - _supla_int16_t ProductID; - - unsigned _supla_int_t Flags; - unsigned char ProtocolVersion; - char online; - - TSuplaChannelValue_B value; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannel_D; // ver. >= 15 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannel_C - items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelPack_C; // ver. >= 10 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannel_D - items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelPack_D; // ver. >= 15 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t LocationID; - _supla_int_t Func; - _supla_int_t AltIcon; - unsigned _supla_int_t Flags; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNELGROUP_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannelGroup; // ver. >= 9 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t Id; - _supla_int_t LocationID; - _supla_int_t Func; - _supla_int_t AltIcon; - _supla_int_t UserIcon; - unsigned _supla_int_t Flags; - - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNELGROUP_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SuplaChannelGroup_B; // ver. >= 10 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannelGroup - items[SUPLA_CHANNELGROUP_PACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelGroupPack; // ver. >= 9 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannelGroup_B - items[SUPLA_CHANNELGROUP_PACK_MAXCOUNT]; // Last variable in struct! -} TSC_SuplaChannelGroupPack_B; // ver. >= 10 - -typedef struct { - // server -> client - char EOL; // End Of List - - _supla_int_t ChannelGroupID; - _supla_int_t ChannelID; -} TSC_SuplaChannelGroupRelation; // ver. >= 9 - -typedef struct { - // server -> client - - _supla_int_t count; - _supla_int_t total_left; - TSC_SuplaChannelGroupRelation - items[SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT]; // Last variable in - // struct! -} TSC_SuplaChannelGroupRelationPack; // ver. >= 9 - -typedef struct { - // client -> server - - _supla_int_t AccessID; - char AccessIDpwd[SUPLA_ACCESSID_PWD_MAXSIZE]; // UTF8 - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; -} TCS_SuplaRegisterClient; - -typedef struct { - // client -> server - - _supla_int_t AccessID; - char AccessIDpwd[SUPLA_ACCESSID_PWD_MAXSIZE]; // UTF8 - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; -} TCS_SuplaRegisterClient_B; // ver. >= 6 - -typedef struct { - // client -> server - - char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 - char AuthKey[SUPLA_AUTHKEY_SIZE]; - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; -} TCS_SuplaRegisterClient_C; // ver. >= 7 - -typedef struct { - // client -> server - - char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 - char Password[SUPLA_PASSWORD_MAXSIZE]; // Optional - UTF8 - char AuthKey[SUPLA_AUTHKEY_SIZE]; - - char GUID[SUPLA_GUID_SIZE]; - char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 - char SoftVer[SUPLA_SOFTVER_MAXSIZE]; - - char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; -} TCS_SuplaRegisterClient_D; // ver. >= 12 - -typedef struct { - // server -> client - - _supla_int_t result_code; - _supla_int_t ClientID; - _supla_int_t LocationCount; - _supla_int_t ChannelCount; - unsigned char activity_timeout; - unsigned char version; - unsigned char version_min; -} TSC_SuplaRegisterClientResult; - -typedef struct { - // server -> client - - _supla_int_t result_code; - _supla_int_t ClientID; - _supla_int_t LocationCount; - _supla_int_t ChannelCount; - _supla_int_t ChannelGroupCount; - _supla_int_t Flags; - unsigned char activity_timeout; - unsigned char version; - unsigned char version_min; -} TSC_SuplaRegisterClientResult_B; // ver. >= 9 - -typedef struct { - // server -> client - - _supla_int_t result_code; - _supla_int_t ClientID; - _supla_int_t LocationCount; - _supla_int_t ChannelCount; - _supla_int_t ChannelGroupCount; - _supla_int_t Flags; - unsigned char activity_timeout; - unsigned char version; - unsigned char version_min; - unsigned _supla_int_t serverUnixTimestamp; // current server time -} TSC_SuplaRegisterClientResult_C; // ver. >= 17 - -typedef struct { - // client -> server - unsigned char ChannelId; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TCS_SuplaChannelNewValue; // Deprecated - -typedef struct { - // client -> server - _supla_int_t ChannelId; - char value[SUPLA_CHANNELVALUE_SIZE]; -} TCS_SuplaChannelNewValue_B; - -typedef struct { - // client -> server - _supla_int_t Id; - char Target; // SUPLA_TARGET_ - char value[SUPLA_CHANNELVALUE_SIZE]; -} TCS_SuplaNewValue; // ver. >= 9 - -typedef struct { - // server -> client - _supla_int_t Event; - _supla_int_t ChannelID; - unsigned _supla_int_t DurationMS; - - _supla_int_t SenderID; - unsigned _supla_int_t - SenderNameSize; // including the terminating null byte ('\0') - char - SenderName[SUPLA_SENDER_NAME_MAXSIZE]; // Last variable in struct! | UTF8 -} TSC_SuplaEvent; - -typedef struct { - char Platform; - - _supla_int_t Param1; - _supla_int_t Param2; - _supla_int_t Param3; - _supla_int_t Param4; -} TDS_FirmwareUpdateParams; - -typedef struct { - char available_protocols; - char host[SUPLA_URL_HOST_MAXSIZE]; - _supla_int_t port; - char path[SUPLA_URL_PATH_MAXSIZE]; -} TSD_FirmwareUpdate_Url; - -typedef struct { - char exists; - TSD_FirmwareUpdate_Url url; -} TSD_FirmwareUpdate_UrlResult; - -typedef struct { - unsigned _supla_int_t client_timestamp; // time >= now == enabled - unsigned _supla_int_t iodevice_timestamp; // time >= now == enabled -} TSDC_RegistrationEnabled; - -typedef struct { - unsigned _supla_int_t ExpiresIn; - unsigned _supla_int_t - TokenSize; // including the terminating null byte ('\0') - char Token[SUPLA_OAUTH_TOKEN_MAXSIZE]; // Last variable in struct! -} TSC_OAuthToken; // ver. >= 10 - -typedef struct { - unsigned char ResultCode; - TSC_OAuthToken Token; -} TSC_OAuthTokenRequestResult; // ver. >= 10 - -typedef struct { - // 3 phases - unsigned _supla_int16_t freq; // * 0.01 Hz - unsigned _supla_int16_t voltage[3]; // * 0.01 V - unsigned _supla_int16_t - current[3]; // * 0.001 A (0.01A FOR EM_VAR_CURRENT_OVER_65A) - _supla_int_t power_active[3]; // * 0.00001 W or kW - _supla_int_t power_reactive[3]; // * 0.00001 var or kvar - _supla_int_t power_apparent[3]; // * 0.00001 VA or kVA - _supla_int16_t power_factor[3]; // * 0.001 - _supla_int16_t phase_angle[3]; // * 0.1 degree -} TElectricityMeter_Measurement; // v. >= 10 - -#define EM_VAR_FREQ 0x0001 -#define EM_VAR_VOLTAGE 0x0002 -#define EM_VAR_CURRENT 0x0004 -#define EM_VAR_POWER_ACTIVE 0x0008 -#define EM_VAR_POWER_REACTIVE 0x0010 -#define EM_VAR_POWER_APPARENT 0x0020 -#define EM_VAR_POWER_FACTOR 0x0040 -#define EM_VAR_PHASE_ANGLE 0x0080 -#define EM_VAR_FORWARD_ACTIVE_ENERGY 0x0100 -#define EM_VAR_REVERSE_ACTIVE_ENERGY 0x0200 -#define EM_VAR_FORWARD_REACTIVE_ENERGY 0x0400 -#define EM_VAR_REVERSE_REACTIVE_ENERGY 0x0800 -#define EM_VAR_CURRENT_OVER_65A 0x1000 -#define EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED 0x2000 -#define EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED 0x4000 -#define EM_VAR_ALL 0xFFFF - -#define EM_VAR_POWER_ACTIVE_KWH 0x100000 -#define EM_VAR_POWER_REACTIVE_KVAR 0x200000 -#define EM_VAR_POWER_APPARENT_KVA 0x400000 - -#ifdef __AVR__ -#define EM_MEASUREMENT_COUNT 1 -#else -#define EM_MEASUREMENT_COUNT 5 -#endif - -#ifdef USE_DEPRECATED_EMEV_V1 -// [IODevice->Server->Client] -typedef struct { - unsigned _supla_int64_t total_forward_active_energy[3]; // * 0.00001 kWh - unsigned _supla_int64_t total_reverse_active_energy[3]; // * 0.00001 kWh - unsigned _supla_int64_t total_forward_reactive_energy[3]; // * 0.00001 kvarh - unsigned _supla_int64_t total_reverse_reactive_energy[3]; // * 0.00001 kvarh - - // The price per unit, total cost and currency is overwritten by the server - // total_cost == SUM(total_forward_active_energy[n] * price_per_unit - _supla_int_t total_cost; // * 0.01 - _supla_int_t price_per_unit; // * 0.0001 - // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm - char currency[3]; - - _supla_int_t measured_values; - _supla_int_t period; // Approximate period between measurements in seconds - _supla_int_t m_count; - TElectricityMeter_Measurement m[EM_MEASUREMENT_COUNT]; // Last variable in - // struct! -} TElectricityMeter_ExtendedValue; // v. >= 10 -#endif /*USE_DEPRECATED_EMEV_V1*/ - -// [IODevice->Server->Client] -typedef struct { - unsigned _supla_int64_t total_forward_active_energy[3]; // * 0.00001 kWh - unsigned _supla_int64_t total_reverse_active_energy[3]; // * 0.00001 kWh - unsigned _supla_int64_t total_forward_reactive_energy[3]; // * 0.00001 kvarh - unsigned _supla_int64_t total_reverse_reactive_energy[3]; // * 0.00001 kvarh - unsigned _supla_int64_t - total_forward_active_energy_balanced; // * 0.00001 kWh - // Vector phase-to-phase balancing - unsigned _supla_int64_t - total_reverse_active_energy_balanced; // * 0.00001 kWh - // Vector phase-to-phase balancing - - // The price per unit, total cost and currency is overwritten by the server - // total_cost == SUM(total_forward_active_energy[n] * price_per_unit - _supla_int_t total_cost; // * 0.01 - _supla_int_t total_cost_balanced; // * 0.01 - _supla_int_t price_per_unit; // * 0.0001 - // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm - char currency[3]; - - _supla_int_t measured_values; - _supla_int_t period; // Approximate period between measurements in seconds - _supla_int_t m_count; - TElectricityMeter_Measurement m[EM_MEASUREMENT_COUNT]; // Last variable in - // struct! -} TElectricityMeter_ExtendedValue_V2; // v. >= 12 - -#define EM_VALUE_FLAG_PHASE1_ON 0x01 -#define EM_VALUE_FLAG_PHASE2_ON 0x02 -#define EM_VALUE_FLAG_PHASE3_ON 0x04 - -// [IODevice->Server->Client] -typedef struct { - char flags; - unsigned _supla_int_t total_forward_active_energy; // * 0.01 kW -} TElectricityMeter_Value; // v. >= 10 - -typedef struct { - // The price per unit, total cost and currency is overwritten by the server - // total_cost = calculated_value * price_per_unit - _supla_int_t total_cost; // * 0.01 - _supla_int_t price_per_unit; // * 0.0001 - // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm - char currency[3]; - char custom_unit[9]; // UTF8 including the terminating null byte ('\0') - - _supla_int_t impulses_per_unit; - unsigned _supla_int64_t counter; - _supla_int64_t calculated_value; // * 0.001 -} TSC_ImpulseCounter_ExtendedValue; // v. >= 10 - -typedef struct { - unsigned _supla_int64_t counter; -} TDS_ImpulseCounter_Value; - -#define RS_VALUE_FLAG_TILT_IS_SET 0x1 -#define RS_VALUE_FLAG_CALIBRATION_FAILED 0x2 -#define RS_VALUE_FLAG_CALIBRATION_LOST 0x4 -#define RS_VALUE_FLAG_MOTOR_PROBLEM 0x8 -#define RS_VALUE_FLAG_CALIBRATION_IN_PROGRESS 0x10 - -typedef struct { - char position; // -1 == calibration. -1 - 100% - char tilt; - char bottom_position; // Percentage points to the windowsill - _supla_int16_t flags; -} TRollerShutterValue; - -typedef struct { - unsigned _supla_int64_t calculated_value; // * 0.001 -} TSC_ImpulseCounter_Value; // v. >= 10 - -typedef struct { - char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 - char Password[SUPLA_PASSWORD_MAXSIZE]; // UTF8 -} TCS_SuperUserAuthorizationRequest; // v. >= 10 - -typedef struct { - _supla_int_t Result; -} TSC_SuperUserAuthorizationResult; // v. >= 10 - -#define SUPLA_CALCFG_RESULT_FALSE 0 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_TRUE 1 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_DONE 2 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_IN_PROGRESS 3 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_NODE_FOUND 4 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_SENDER_CONFLICT 100 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_TIMEOUT 101 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_NOT_SUPPORTED 102 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_ID_NOT_EXISTS 103 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_UNAUTHORIZED 104 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_DEBUG 105 // ver. >= 12 -#define SUPLA_CALCFG_RESULT_NOT_SUPPORTED_IN_SLAVE_MODE 106 // ver. >= 12 - -#define SUPLA_CALCFG_CMD_GET_CHANNEL_FUNCLIST 1000 // v. >= 11 -#define SUPLA_CALCFG_CMD_CANCEL_ALL_CLIENT_COMMANDS 1010 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_RESET_AND_CLEAR 2000 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_ADD_NODE 2010 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_REMOVE_NODE 2020 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_GET_NODE_LIST 2030 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_GET_ASSIGNED_NODE_ID 2040 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_ASSIGN_NODE_ID 2050 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_GET_WAKE_UP_SETTINGS 2060 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_SET_WAKE_UP_TIME 2070 // v. >= 12 -#define SUPLA_CALCFG_CMD_ZWAVE_CONFIG_MODE_ACTIVE 4000 // v. >= 12 -#define SUPLA_CALCFG_CMD_DEBUG_STRING 5000 // v. >= 12 -#define SUPLA_CALCFG_CMD_PROGRESS_REPORT 5001 // v. >= 12 -#define SUPLA_CALCFG_CMD_SET_LIGHTSOURCE_LIFESPAN 6000 // v. >= 12 -#define SUPLA_CALCFG_CMD_RESET_COUNTERS 7000 // v. >= 15 -#define SUPLA_CALCFG_CMD_RECALIBRATE 8000 // v. >= 15 - -#define SUPLA_CALCFG_DATATYPE_RS_SETTINGS 1000 - -#define CALCFG_ZWAVE_SCREENTYPE_UNKNOWN 0 -#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL 1 -#define CALCFG_ZWAVE_SCREENTYPE_BINARY 2 -#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL_AUTOSHADE 3 -#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL_COLOR_CONTROL 4 -#define CALCFG_ZWAVE_SCREENTYPE_BINARY_COLOR_CONTROL 5 -#define CALCFG_ZWAVE_SCREENTYPE_SENSOR 6 - -#define ZWAVE_NODE_NAME_MAXSIZE 50 - -#define ZWAVE_NODE_FLAG_CHANNEL_ASSIGNED 0x1 -#define ZWAVE_NODE_FLAG_WAKEUP_TIME_SETTABLE 0x2 - -typedef struct { - unsigned char Id; - unsigned char Flags; - union { - unsigned char ChannelNumber; - _supla_int_t ChannelID; - }; - unsigned char ScreenType; - unsigned char NameSize; // including the terminating null byte ('\0') - char Name[ZWAVE_NODE_NAME_MAXSIZE]; // UTF8. Last variable in struct! -} TCalCfg_ZWave_Node; // v. >= 12 - -typedef struct { - unsigned _supla_int_t MinimumSec : 24; - unsigned _supla_int_t MaximumSec : 24; - unsigned _supla_int_t ValueSec : 24; - unsigned _supla_int_t IntervalStepSec : 24; -} TCalCfg_ZWave_WakeupSettingsReport; - -typedef struct { - unsigned _supla_int_t TimeSec : 24; -} TCalCfg_ZWave_WakeUpTime; - -typedef struct { - _supla_int_t Command; - unsigned char Progress; // 0 - 100% -} TCalCfg_ProgressReport; - -typedef struct { - unsigned char ResetCounter; // 0 - NO, 1 - YES - unsigned char SetTime; // 0 - NO, 1 - YES - unsigned short LightSourceLifespan; // 0 - 65535 hours -} TCalCfg_LightSourceLifespan; - -// CALCFG == CALIBRATION / CONFIG -typedef struct { - _supla_int_t ChannelID; - _supla_int_t Command; - _supla_int_t DataType; - unsigned _supla_int_t DataSize; - char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! -} TCS_DeviceCalCfgRequest; // v. >= 10 - -// CALCFG == CALIBRATION / CONFIG -typedef struct { - _supla_int_t Id; - char Target; // SUPLA_TARGET_ - _supla_int_t Command; - _supla_int_t DataType; - unsigned _supla_int_t DataSize; - char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! -} TCS_DeviceCalCfgRequest_B; // v. >= 11 - -typedef struct { - _supla_int_t ChannelID; - _supla_int_t Command; - _supla_int_t Result; - unsigned _supla_int_t DataSize; - char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! -} TSC_DeviceCalCfgResult; // v. >= 10 - -typedef struct { - _supla_int_t SenderID; - _supla_int_t ChannelNumber; - _supla_int_t Command; - char SuperUserAuthorized; - _supla_int_t DataType; - unsigned _supla_int_t DataSize; - char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! -} TSD_DeviceCalCfgRequest; // v. >= 10 - -typedef struct { - _supla_int_t ReceiverID; - _supla_int_t ChannelNumber; - _supla_int_t Command; - _supla_int_t Result; - unsigned _supla_int_t DataSize; - char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! -} TDS_DeviceCalCfgResult; // v. >= 10 - -typedef struct { - _supla_int_t FullOpeningTimeMS; - _supla_int_t FullClosingTimeMS; -} TCalCfg_RollerShutterSettings; - -#define RGBW_BRIGHTNESS_ONOFF 0x1 -#define RGBW_COLOR_ONOFF 0x2 - -typedef struct { - char brightness; - char colorBrightness; - char B; - char G; - char R; - char onOff; -} TRGBW_Value; // v. >= 10 - -#define SUPLA_RELAY_FLAG_OVERCURRENT_RELAY_OFF 0x1 - -typedef struct { - char hi; // actual state of relay - 0 turned off, >= 1 - turned on - unsigned short flags; // SUPLA_RELAY_FLAG_* -} TRelayChannel_Value; // v. >= 15 - -#define DIGIGLASS_TOO_LONG_OPERATION_WARNING 0x1 -#define DIGIGLASS_PLANNED_REGENERATION_IN_PROGRESS 0x2 -#define DIGIGLASS_REGENERATION_AFTER_20H_IN_PROGRESS 0x4 - -typedef struct { - unsigned char flags; - unsigned char sectionCount; // 1 - 16 Filled by server - unsigned short mask; // bit mask. 0 - opaque, 1 - transparent -} TDigiglass_Value; // v. >= 14 - -typedef struct { - unsigned short mask; // Bit mask. 0 - opaque, 1 - transparent - unsigned short - active_bits; // Specifies which bits of the mask are not skipped -} TCSD_Digiglass_NewValue; // v. >= 14 - -typedef struct { - unsigned char sec; // 0-59 - unsigned char min; // 0-59 - unsigned char hour; // 0-24 - unsigned char dayOfWeek; // 1 = Sunday, 2 = Monday, …, 7 = Saturday -} TThermostat_Time; // v. >= 11 - -#define THERMOSTAT_SCHEDULE_DAY_SUNDAY 0x01 -#define THERMOSTAT_SCHEDULE_DAY_MONDAY 0x02 -#define THERMOSTAT_SCHEDULE_DAY_TUESDAY 0x04 -#define THERMOSTAT_SCHEDULE_DAY_WEDNESDAY 0x08 -#define THERMOSTAT_SCHEDULE_DAY_THURSDAY 0x10 -#define THERMOSTAT_SCHEDULE_DAY_FRIDAY 0x20 -#define THERMOSTAT_SCHEDULE_DAY_SATURDAY 0x40 -#define THERMOSTAT_SCHEDULE_DAY_ALL 0xFF - -#define THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_TEMPERATURE 0 -#define THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_PROGRAM 1 - -typedef struct { - unsigned char ValueType; // THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_ - char HourValue[7][24]; // 7 days x 24h - // 0 = Sunday, 1 = Monday, …, 6 = Saturday -} TThermostat_Schedule; // v. >= 11 - -typedef struct { - unsigned char ValueType; // THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_ - unsigned char WeekDays; // THERMOSTAT_SCHEDULE_DAY_ - char HourValue[24]; -} TThermostatValueGroup; // v. >= 11 - -typedef struct { - TThermostatValueGroup Group[4]; -} TThermostat_ScheduleCfg; // v. >= 11 - -#define TEMPERATURE_INDEX1 0x0001 -#define TEMPERATURE_INDEX2 0x0002 -#define TEMPERATURE_INDEX3 0x0004 -#define TEMPERATURE_INDEX4 0x0008 -#define TEMPERATURE_INDEX5 0x0010 -#define TEMPERATURE_INDEX6 0x0020 -#define TEMPERATURE_INDEX7 0x0040 -#define TEMPERATURE_INDEX8 0x0080 -#define TEMPERATURE_INDEX9 0x0100 -#define TEMPERATURE_INDEX10 0x0200 - -typedef struct { - _supla_int16_t Index; // BIT0 Temperature[0], BIT1 Temperature[1] etc... - unsigned _supla_int16_t Temperature[10]; -} TThermostatTemperatureCfg; - -// Thermostat configuration commands - ver. >= 11 -#define SUPLA_THERMOSTAT_CMD_TURNON 1 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_AUTO 2 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_COOL 3 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_HEAT 4 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_NORMAL 5 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_ECO 6 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_TURBO 7 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_DRY 8 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_FANONLY 9 -#define SUPLA_THERMOSTAT_CMD_SET_MODE_PURIFIER 10 -#define SUPLA_THERMOSTAT_CMD_SET_SCHEDULE 11 -#define SUPLA_THERMOSTAT_CMD_SET_TIME 12 -#define SUPLA_THERMOSTAT_CMD_SET_TEMPERATURE 13 - -// Thermostat capability flags - ver. >= 11 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_ONOFF 0x0001 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_AUTO 0x0002 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_COOL 0x0004 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_HEAT 0x0008 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_ECO 0x0010 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_DRY 0x0020 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_FANONLY 0x0040 -#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_PURIFIER 0x0080 -#define SUPLA_THERMOSTAT_CAP_FLAG_SCHEDULE 0x0100 - -// Thermostat value flags - ver. >= 11 -#define SUPLA_THERMOSTAT_VALUE_FLAG_ON 0x0001 -#define SUPLA_THERMOSTAT_VALUE_FLAG_AUTO_MODE 0x0002 -#define SUPLA_THERMOSTAT_VALUE_FLAG_COOL_MODE 0x0004 -#define SUPLA_THERMOSTAT_VALUE_FLAG_HEAT_MODE 0x0008 -#define SUPLA_THERMOSTAT_VALUE_FLAG_ECO_MODE 0x0010 -#define SUPLA_THERMOSTAT_VALUE_FLAG_DRY_MODE 0x0020 -#define SUPLA_THERMOSTAT_VALUE_FLAG_FANONLY_MODE 0x0040 -#define SUPLA_THERMOSTAT_VALUE_FLAG_PURIFIER_MODE 0x0080 - -// Thermostat fields - ver. >= 11 -#define THERMOSTAT_FIELD_MeasuredTemperatures 0x01 -#define THERMOSTAT_FIELD_PresetTemperatures 0x02 -#define THERMOSTAT_FIELD_Flags 0x04 -#define THERMOSTAT_FIELD_Values 0x08 -#define THERMOSTAT_FIELD_Time 0x10 -#define THERMOSTAT_FIELD_Schedule 0x20 - -typedef struct { - unsigned char Fields; - _supla_int16_t MeasuredTemperature[10]; // * 0.01 - _supla_int16_t PresetTemperature[10]; // * 0.01 - _supla_int16_t Flags[8]; - _supla_int16_t Values[8]; - TThermostat_Time Time; - TThermostat_Schedule Schedule; // 7 days x 24h (4bit/hour) -} TThermostat_ExtendedValue; // v. >= 11 - -typedef struct { - unsigned char IsOn; - unsigned char Flags; - _supla_int16_t MeasuredTemperature; // * 0.01 - _supla_int16_t PresetTemperature; // * 0.01 -} TThermostat_Value; // v. >= 11 - -typedef struct { - unsigned _supla_int16_t year; - unsigned char month; - unsigned char day; - unsigned char dayOfWeek; // 1 = Sunday, 2 = Monday, …, 7 = Saturday - unsigned char hour; - unsigned char min; - unsigned char sec; - unsigned _supla_int_t - timezoneSize; // including the terminating null byte ('\0') - char timezone[SUPLA_TIMEZONE_MAXSIZE]; // Last variable in struct! -} TSDC_UserLocalTimeResult; - -typedef struct { - _supla_int_t SenderID; - union { - _supla_int_t ChannelID; // Client -> Server - unsigned char ChannelNumber; // Server -> Device - }; -} TCSD_ChannelStateRequest; // v. >= 12 Client -> Server -> Device - -#define SUPLA_CHANNELSTATE_FIELD_IPV4 0x0001 -#define SUPLA_CHANNELSTATE_FIELD_MAC 0x0002 -#define SUPLA_CHANNELSTATE_FIELD_BATTERYLEVEL 0x0004 -#define SUPLA_CHANNELSTATE_FIELD_BATTERYPOWERED 0x0008 -#define SUPLA_CHANNELSTATE_FIELD_WIFIRSSI 0x0010 -#define SUPLA_CHANNELSTATE_FIELD_WIFISIGNALSTRENGTH 0x0020 -#define SUPLA_CHANNELSTATE_FIELD_BRIDGENODESIGNALSTRENGTH 0x0040 -#define SUPLA_CHANNELSTATE_FIELD_UPTIME 0x0080 -#define SUPLA_CHANNELSTATE_FIELD_CONNECTIONUPTIME 0x0100 -#define SUPLA_CHANNELSTATE_FIELD_BATTERYHEALTH 0x0200 -#define SUPLA_CHANNELSTATE_FIELD_BRIDGENODEONLINE 0x0400 -#define SUPLA_CHANNELSTATE_FIELD_LASTCONNECTIONRESETCAUSE 0x0800 -#define SUPLA_CHANNELSTATE_FIELD_LIGHTSOURCELIFESPAN 0x1000 -#define SUPLA_CHANNELSTATE_FIELD_LIGHTSOURCEOPERATINGTIME 0x2000 - -#define SUPLA_LASTCONNECTIONRESETCAUSE_UNKNOWN 0 -#define SUPLA_LASTCONNECTIONRESETCAUSE_ACTIVITY_TIMEOUT 1 -#define SUPLA_LASTCONNECTIONRESETCAUSE_WIFI_CONNECTION_LOST 2 -#define SUPLA_LASTCONNECTIONRESETCAUSE_SERVER_CONNECTION_LOST 3 - -typedef struct { - _supla_int_t ReceiverID; // Not used in extended values - union { - // Not used in extended values - _supla_int_t ChannelID; // Server -> Client - unsigned char ChannelNumber; // Device -> Server - }; - _supla_int_t Fields; - _supla_int_t defaultIconField; // SUPLA_CHANNELSTATE_FIELD_* - unsigned _supla_int_t IPv4; - unsigned char MAC[6]; - unsigned char BatteryLevel; // 0 - 100% - unsigned char BatteryPowered; // true(1)/false(0) - char WiFiRSSI; - unsigned char WiFiSignalStrength; // 0 - 100% - unsigned char BridgeNodeOnline; // 0/1 - unsigned char BridgeNodeSignalStrength; // 0 - 100% - unsigned _supla_int_t Uptime; // sec. - unsigned _supla_int_t ConnectionUptime; // sec. - unsigned char BatteryHealth; - unsigned char LastConnectionResetCause; // SUPLA_LASTCONNECTIONRESETCAUSE_* - unsigned short LightSourceLifespan; // 0 - 65535 hours - union { - short LightSourceLifespanLeft; // -327,67 - 100.00% LightSourceLifespan * - // 0.01 - _supla_int_t LightSourceOperatingTime; // -3932100sec. - 3932100sec. - }; - char EmptySpace[2]; // Empty space for future use -} TDSC_ChannelState; // v. >= 12 Device -> Server -> Client - -#define TChannelState_ExtendedValue TDSC_ChannelState - -typedef struct { - _supla_int_t ChannelID; -} TCS_ChannelBasicCfgRequest; // v. >= 12 - -typedef struct { - union { - // Remaining time to turn off - unsigned _supla_int_t RemainingTimeMs; - unsigned _supla_int_t CountdownEndsAt; // Unix timestamp - Filled by server - }; - - unsigned char TargetValue[SUPLA_CHANNELVALUE_SIZE]; - - _supla_int_t SenderID; - unsigned _supla_int_t - SenderNameSize; // including the terminating null byte ('\0') - char SenderName[SUPLA_SENDER_NAME_MAXSIZE]; // Last variable in struct! - // UTF8 | Filled by server -} TTimerState_ExtendedValue; - -typedef struct { - TChannelState_ExtendedValue Channel; - TTimerState_ExtendedValue Timer; // Last variable in struct! -} TChannelAndTimerState_ExtendedValue; - -typedef struct { - char DeviceName[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 - char DeviceSoftVer[SUPLA_SOFTVER_MAXSIZE]; - _supla_int_t DeviceID; - _supla_int_t DeviceFlags; - _supla_int16_t ManufacturerID; - _supla_int16_t ProductID; - - _supla_int_t ID; - unsigned char Number; - _supla_int_t Type; - _supla_int_t Func; - _supla_int_t FuncList; - - unsigned _supla_int_t ChannelFlags; - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_ChannelBasicCfg; // v. >= 12 - -typedef struct { - _supla_int_t ChannelID; - _supla_int_t Func; -} TCS_SetChannelFunction; // v. >= 12 - -typedef struct { - _supla_int_t ChannelID; - _supla_int_t Func; - unsigned char ResultCode; -} TSC_SetChannelFunctionResult; // v. >= 12 - -typedef struct { - _supla_int_t ID; - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CAPTION_MAXSIZE]; // Last variable in struct! -} TCS_SetCaption; // v. >= 12 - -typedef struct { - _supla_int_t ID; - unsigned char ResultCode; - unsigned _supla_int_t - CaptionSize; // including the terminating null byte ('\0') - char Caption[SUPLA_CAPTION_MAXSIZE]; // Last variable in struct! -} TSC_SetCaptionResult; // v. >= 12 - -typedef struct { - unsigned char ResultCode; -} TSC_ClientsReconnectRequestResult; // v. >= 12 - -typedef struct { - // Disabled: 0 - // Ignore: <0 - _supla_int_t IODeviceRegistrationTimeSec; - _supla_int_t ClientRegistrationTimeSec; -} TCS_SetRegistrationEnabled; // v. >= 12 - -typedef struct { - unsigned char ResultCode; -} TSC_SetRegistrationEnabledResult; // v. >= 12 - -typedef struct { - int DeviceID; -} TCS_DeviceReconnectRequest; // v. >= 12 - -typedef struct { - int DeviceID; - unsigned char ResultCode; -} TSC_DeviceReconnectRequestResult; // v. >= 12 - -typedef struct { - // server -> device - - unsigned char ChannelCount; - _supla_int_t Functions[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! - // Functions[ChannelNumber] -} TSD_ChannelFunctions; // ver. >= 12 - -typedef struct { - unsigned char ChannelNumber; -} TDS_GetChannelIntParamsRequest; - -typedef struct { - unsigned char ChannelNumber; - _supla_int_t Param1; - _supla_int_t Param2; - _supla_int_t Param3; -} TSD_ChannelIntParams; - -#define SUPLA_CHANNEL_CONFIG_MAXSIZE 128 -#define SUPLA_CONFIG_TYPE_DEFAULT 0 - -typedef struct { - unsigned char ChannelNumber; - unsigned char ConfigType; - unsigned _supla_int_t Flags; -} TDS_GetChannelConfigRequest; // v. >= 16 - -typedef struct { - unsigned char ChannelNumber; - _supla_int_t Func; - unsigned char ConfigType; - unsigned short ConfigSize; - char Config[SUPLA_CHANNEL_CONFIG_MAXSIZE]; // Last variable in struct! v. >= - // 16. TSD_DeviceChannelConfig_* -} TSD_ChannelConfig; - -typedef struct { - _supla_int_t TimeMS; -} TSD_ChannelConfig_StaircaseTimer; // v. >= 16 - -typedef struct { - _supla_int_t ClosingTimeMS; - _supla_int_t OpeningTimeMS; -} TSD_ChannelConfig_Rollershutter; // v. >= 16 - -typedef struct { - unsigned _supla_int_t ActiveActions; -} TSD_ChannelConfig_ActionTrigger; // v. >= 16 - -typedef struct { - _supla_int_t ChannelID; - unsigned _supla_int_t DurationMS; - unsigned char On; -} TCS_TimerArmRequest; // v. >= 17 - -// Recommended for bistable buttons -#define SUPLA_ACTION_CAP_TURN_ON (1 << 0) -#define SUPLA_ACTION_CAP_TURN_OFF (1 << 1) -#define SUPLA_ACTION_CAP_TOGGLE_x1 (1 << 2) -#define SUPLA_ACTION_CAP_TOGGLE_x2 (1 << 3) -#define SUPLA_ACTION_CAP_TOGGLE_x3 (1 << 4) -#define SUPLA_ACTION_CAP_TOGGLE_x4 (1 << 5) -#define SUPLA_ACTION_CAP_TOGGLE_x5 (1 << 6) - -// Recommended for monostable buttons -#define SUPLA_ACTION_CAP_HOLD (1 << 10) -#define SUPLA_ACTION_CAP_SHORT_PRESS_x1 (1 << 11) -#define SUPLA_ACTION_CAP_SHORT_PRESS_x2 (1 << 12) -#define SUPLA_ACTION_CAP_SHORT_PRESS_x3 (1 << 13) -#define SUPLA_ACTION_CAP_SHORT_PRESS_x4 (1 << 14) -#define SUPLA_ACTION_CAP_SHORT_PRESS_x5 (1 << 15) - -#define SUPLA_VALVE_FLAG_FLOODING 0x1 -#define SUPLA_VALVE_FLAG_MANUALLY_CLOSED 0x2 - -typedef struct { - union { - unsigned char closed; - unsigned char closed_percent; - }; - - unsigned char flags; -} TValve_Value; - -typedef struct { - unsigned char ChannelNumber; - _supla_int_t ActionTrigger; - unsigned char zero[10]; // Place for future variables -} TDS_ActionTrigger; - -#pragma pack(pop) - -void *PROTO_ICACHE_FLASH sproto_init(void); -void PROTO_ICACHE_FLASH sproto_free(void *spd_ptr); - -#ifndef SPROTO_WITHOUT_OUT_BUFFER -char PROTO_ICACHE_FLASH sproto_out_buffer_append(void *spd_ptr, - TSuplaDataPacket *sdp); -unsigned _supla_int_t sproto_pop_out_data(void *spd_ptr, char *buffer, - unsigned _supla_int_t buffer_size); -#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ -char PROTO_ICACHE_FLASH sproto_out_dataexists(void *spd_ptr); -char PROTO_ICACHE_FLASH sproto_in_buffer_append( - void *spd_ptr, char *data, unsigned _supla_int_t data_size); - -char PROTO_ICACHE_FLASH sproto_pop_in_sdp(void *spd_ptr, TSuplaDataPacket *sdp); -char PROTO_ICACHE_FLASH sproto_in_dataexists(void *spd_ptr); - -unsigned char PROTO_ICACHE_FLASH sproto_get_version(void *spd_ptr); -void PROTO_ICACHE_FLASH sproto_set_version(void *spd_ptr, - unsigned char version); -void PROTO_ICACHE_FLASH sproto_sdp_init(void *spd_ptr, TSuplaDataPacket *sdp); -char PROTO_ICACHE_FLASH sproto_set_data(TSuplaDataPacket *sdp, char *data, - unsigned _supla_int_t data_size, - unsigned _supla_int_t call_type); -TSuplaDataPacket *PROTO_ICACHE_FLASH sproto_sdp_malloc(void *spd_ptr); -void PROTO_ICACHE_FLASH sproto_sdp_free(TSuplaDataPacket *sdp); - -void PROTO_ICACHE_FLASH sproto_log_summary(void *spd_ptr); -void PROTO_ICACHE_FLASH sproto_buffer_dump(void *spd_ptr, unsigned char in); - -#ifdef __cplusplus -} -#endif - -#endif /* supla_proto_H_ */ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef supla_proto_H_ +#define supla_proto_H_ + +#ifdef _WIN32 + +#include +#define _supla_int_t int +#define _supla_int16_t short +#define _supla_int64_t __int64 +#define _supla_timeval timeval + +#elif defined(__AVR__) + +#define SPROTO_WITHOUT_OUT_BUFFER + +struct _supla_timeval { + long tv_sec[2]; + long tv_usec[2]; +}; + +#define timeval _supla_timeval + +#define _supla_int16_t int +#define _supla_int_t long +#define _supla_int64_t long long + +#elif defined(ESP8266) || defined(ESP32) +#include +#define PROTO_ICACHE_FLASH ICACHE_FLASH_ATTR + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#define SPROTO_WITHOUT_OUT_BUFFER +#endif /*ARDUINO_ARCH_ESP8266*/ + +struct _supla_timeval { + long long tv_sec; + long long tv_usec; +}; + +#define _supla_int16_t short +#define _supla_int_t int +#define _supla_int64_t long long +#elif defined(__arm__) + +struct _supla_timeval { + long long tv_sec; + long long tv_usec; +}; + +#include +#define _supla_int16_t short +#define _supla_int_t int +#define _supla_int64_t long long + +#else /*__arm__*/ +#include +#define _supla_int16_t short +#define _supla_int_t int +#define _supla_int64_t long long +#define _supla_timeval timeval +#endif + +#if defined(ARDUINO) +#undef PROTO_ICACHE_FLASH +#endif /*defined(ARDUINO)*/ + +#ifndef PROTO_ICACHE_FLASH +#define PROTO_ICACHE_FLASH +#endif /*PROTO_ICACHE_FLASH*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SUPLA_TAG_SIZE 5 +extern char sproto_tag[SUPLA_TAG_SIZE]; + +// DCS - device/client -> server +// SDC - server -> device/client +// DS - device -> server +// SD - server -> device +// CS - client -> server +// SC - server -> client + +#define SUPLA_PROTO_VERSION 17 +#define SUPLA_PROTO_VERSION_MIN 1 +#if defined(ARDUINO_ARCH_AVR) // Arduino IDE for Arduino HW +#define SUPLA_MAX_DATA_SIZE 1248 // Registration header + 32 channels x 21 B +#elif defined(ARDUINO_ARCH_ESP8266) || \ + defined(ARDUINO_ARCH_ESP32) // Arduino IDE for ESP8266 +#define SUPLA_MAX_DATA_SIZE 3264 // Registration header + 128 channels x 21 B +#elif defined(ESP8266) +#define SUPLA_MAX_DATA_SIZE 1536 +#else +#define SUPLA_MAX_DATA_SIZE 10240 +#endif +#define SUPLA_RC_MAX_DEV_COUNT 50 +#define SUPLA_SOFTVER_MAXSIZE 21 + +#define SUPLA_CAPTION_MAXSIZE 401 + +#define SUPLA_GUID_SIZE 16 +#define SUPLA_GUID_HEXSIZE 33 +#define SUPLA_LOCATION_PWD_MAXSIZE 33 +#define SUPLA_ACCESSID_PWD_MAXSIZE 33 +#define SUPLA_LOCATION_CAPTION_MAXSIZE SUPLA_CAPTION_MAXSIZE +#define SUPLA_LOCATIONPACK_MAXCOUNT 20 +#define SUPLA_CHANNEL_CAPTION_MAXSIZE SUPLA_CAPTION_MAXSIZE +#define SUPLA_CHANNELPACK_MAXCOUNT 20 +#define SUPLA_URL_HOST_MAXSIZE 101 +#define SUPLA_URL_PATH_MAXSIZE 101 +#define SUPLA_SERVER_NAME_MAXSIZE 65 +#define SUPLA_EMAIL_MAXSIZE 256 // ver. >= 7 +#define SUPLA_PASSWORD_MAXSIZE 64 // ver. >= 10 +#define SUPLA_AUTHKEY_SIZE 16 // ver. >= 7 +#define SUPLA_AUTHKEY_HEXSIZE 33 // ver. >= 7 +#define SUPLA_OAUTH_TOKEN_MAXSIZE 256 // ver. >= 10 +#define SUPLA_CHANNELGROUP_PACK_MAXCOUNT 20 // ver. >= 9 +#define SUPLA_CHANNELGROUP_CAPTION_MAXSIZE 401 // ver. >= 9 +#define SUPLA_CHANNELVALUE_PACK_MAXCOUNT 20 // ver. >= 9 +#define SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXCOUNT 5 // ver. >= 10 +#define SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE \ + (SUPLA_MAX_DATA_SIZE - 50) // ver. >= 10 +#define SUPLA_CALCFG_DATA_MAXSIZE 128 // ver. >= 10 +#define SUPLA_TIMEZONE_MAXSIZE 51 // ver. >= 11 + +#ifndef SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT +#define SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT 100 // ver. >= 9 +#endif /*SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT*/ + +#define SUPLA_DCS_CALL_GETVERSION 10 +#define SUPLA_SDC_CALL_GETVERSION_RESULT 20 +#define SUPLA_SDC_CALL_VERSIONERROR 30 +#define SUPLA_DCS_CALL_PING_SERVER 40 +#define SUPLA_SDC_CALL_PING_SERVER_RESULT 50 +#define SUPLA_DS_CALL_REGISTER_DEVICE 60 +#define SUPLA_DS_CALL_REGISTER_DEVICE_B 65 // ver. >= 2 +#define SUPLA_DS_CALL_REGISTER_DEVICE_C 67 // ver. >= 6 +#define SUPLA_DS_CALL_REGISTER_DEVICE_D 68 // ver. >= 7 +#define SUPLA_DS_CALL_REGISTER_DEVICE_E 69 // ver. >= 10 +#define SUPLA_SD_CALL_REGISTER_DEVICE_RESULT 70 +#define SUPLA_CS_CALL_REGISTER_CLIENT 80 +#define SUPLA_CS_CALL_REGISTER_CLIENT_B 85 // ver. >= 6 +#define SUPLA_CS_CALL_REGISTER_CLIENT_C 86 // ver. >= 7 +#define SUPLA_CS_CALL_REGISTER_CLIENT_D 87 // ver. >= 12 +#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT 90 +#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B 92 // ver. >= 9 +#define SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C 94 // ver. >= 17 +#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED 100 +#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B 102 // ver. >= 12 +#define SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C 103 // ver. >= 12 +#define SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED 105 // ver. >= 10 +#define SUPLA_SD_CALL_CHANNEL_SET_VALUE 110 +#define SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE 115 // ver. >= 13 +#define SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT 120 +#define SUPLA_SC_CALL_LOCATION_UPDATE 130 +#define SUPLA_SC_CALL_LOCATIONPACK_UPDATE 140 +#define SUPLA_SC_CALL_CHANNEL_UPDATE 150 +#define SUPLA_SC_CALL_CHANNELPACK_UPDATE 160 +#define SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE 170 +#define SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B 171 +#define SUPLA_CS_CALL_GET_NEXT 180 +#define SUPLA_SC_CALL_EVENT 190 +#define SUPLA_CS_CALL_CHANNEL_SET_VALUE 200 +#define SUPLA_CS_CALL_CHANNEL_SET_VALUE_B 205 // ver. >= 3 +#define SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT 210 // ver. >= 2 +#define SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT 220 // ver. >= 2 +#define SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL 300 // ver. >= 5 +#define SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT 310 // ver. >= 5 +#define SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED 320 // ver. >= 7 +#define SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT 330 // ver. >= 7 +#define SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST 340 // ver. >= 10 +#define SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT 350 // ver. >= 10 +#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_B 360 // ver. >= 8 +#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_C 361 // ver. >= 10 +#define SUPLA_SC_CALL_CHANNELPACK_UPDATE_D 362 // ver. >= 15 +#define SUPLA_SC_CALL_CHANNEL_UPDATE_B 370 // ver. >= 8 +#define SUPLA_SC_CALL_CHANNEL_UPDATE_C 371 // ver. >= 10 +#define SUPLA_SC_CALL_CHANNEL_UPDATE_D 372 // ver. >= 15 +#define SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE 380 // ver. >= 9 +#define SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B 381 // ver. >= 10 +#define SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE 390 // ver. >= 9 +#define SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE 400 // ver. >= 9 +#define SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B 401 // ver. >= 15 +#define SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE 405 // ver. >= 10 +#define SUPLA_CS_CALL_SET_VALUE 410 // ver. >= 9 +#define SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST 420 // ver. >= 10 +#define SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT 425 // ver. >= 12 +#define SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT 430 // ver. >= 10 +#define SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST 440 // ver. >= 10 +#define SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B 445 // ver. >= 11 +#define SUPLA_SC_CALL_DEVICE_CALCFG_RESULT 450 // ver. >= 10 +#define SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST 460 // ver. >= 10 +#define SUPLA_DS_CALL_DEVICE_CALCFG_RESULT 470 // ver. >= 10 +#define SUPLA_DCS_CALL_GET_USER_LOCALTIME 480 // ver. >= 11 +#define SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT 490 // ver. >= 11 +#define SUPLA_CSD_CALL_GET_CHANNEL_STATE 500 // ver. >= 12 +#define SUPLA_DSC_CALL_CHANNEL_STATE_RESULT 510 // ver. >= 12 +#define SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG 520 // ver. >= 12 +#define SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT 530 // ver. >= 12 +#define SUPLA_CS_CALL_SET_CHANNEL_FUNCTION 540 // ver. >= 12 +#define SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT 550 // ver. >= 12 +#define SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST 560 // ver. >= 12 +#define SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT 570 // ver. >= 12 +#define SUPLA_CS_CALL_SET_REGISTRATION_ENABLED 580 // ver. >= 12 +#define SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT 590 // ver. >= 12 +#define SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST 600 // ver. >= 12 +#define SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT 610 // ver. >= 12 +#define SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS 620 // ver. >= 12 +#define SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT 630 // ver. >= 12 +#define SUPLA_CS_CALL_SET_CHANNEL_CAPTION 640 // ver. >= 12 +#define SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT 650 // ver. >= 12 +#define SUPLA_CS_CALL_SET_LOCATION_CAPTION 645 // ver. >= 14 +#define SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT 655 // ver. >= 14 +#define SUPLA_DS_CALL_GET_CHANNEL_CONFIG 680 // ver. >= 16 +#define SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT 690 // ver. >= 16 +#define SUPLA_DS_CALL_ACTIONTRIGGER 700 // ver. >= 16 +#define SUPLA_CS_CALL_TIMER_ARM 800 // ver. >= 17 + +#define SUPLA_RESULT_CALL_NOT_ALLOWED -5 +#define SUPLA_RESULT_DATA_TOO_LARGE -4 +#define SUPLA_RESULT_BUFFER_OVERFLOW -3 +#define SUPLA_RESULT_DATA_ERROR -2 +#define SUPLA_RESULT_VERSION_ERROR -1 +#define SUPLA_RESULT_FALSE 0 +#define SUPLA_RESULT_TRUE 1 + +#define SUPLA_RESULTCODE_NONE 0 +#define SUPLA_RESULTCODE_UNSUPORTED 1 +#define SUPLA_RESULTCODE_FALSE 2 +#define SUPLA_RESULTCODE_TRUE 3 +#define SUPLA_RESULTCODE_TEMPORARILY_UNAVAILABLE 4 +#define SUPLA_RESULTCODE_BAD_CREDENTIALS 5 +#define SUPLA_RESULTCODE_LOCATION_CONFLICT 6 +#define SUPLA_RESULTCODE_CHANNEL_CONFLICT 7 +#define SUPLA_RESULTCODE_DEVICE_DISABLED 8 +#define SUPLA_RESULTCODE_ACCESSID_DISABLED 9 +#define SUPLA_RESULTCODE_LOCATION_DISABLED 10 +#define SUPLA_RESULTCODE_CLIENT_DISABLED 11 +#define SUPLA_RESULTCODE_CLIENT_LIMITEXCEEDED 12 +#define SUPLA_RESULTCODE_DEVICE_LIMITEXCEEDED 13 +#define SUPLA_RESULTCODE_GUID_ERROR 14 +#define SUPLA_RESULTCODE_HOSTNOTFOUND 15 // ver. >= 5 +#define SUPLA_RESULTCODE_CANTCONNECTTOHOST 16 // ver. >= 5 +#define SUPLA_RESULTCODE_REGISTRATION_DISABLED 17 // ver. >= 7 +#define SUPLA_RESULTCODE_ACCESSID_NOT_ASSIGNED 18 // ver. >= 7 +#define SUPLA_RESULTCODE_AUTHKEY_ERROR 19 // ver. >= 7 +#define SUPLA_RESULTCODE_NO_LOCATION_AVAILABLE 20 // ver. >= 7 +#define SUPLA_RESULTCODE_USER_CONFLICT 21 // Deprecated +#define SUPLA_RESULTCODE_UNAUTHORIZED 22 // ver. >= 10 +#define SUPLA_RESULTCODE_AUTHORIZED 23 // ver. >= 10 +#define SUPLA_RESULTCODE_NOT_ALLOWED 24 // ver. >= 12 +#define SUPLA_RESULTCODE_CHANNELNOTFOUND 25 // ver. >= 12 +#define SUPLA_RESULTCODE_UNKNOWN_ERROR 26 // ver. >= 12 +#define SUPLA_RESULTCODE_DENY_CHANNEL_BELONG_TO_GROUP 27 // ver. >= 12 +#define SUPLA_RESULTCODE_DENY_CHANNEL_HAS_SCHEDULE 28 // ver. >= 12 +#define SUPLA_RESULTCODE_DENY_CHANNEL_IS_ASSOCIETED_WITH_SCENE 29 // ver. >= 12 +#define SUPLA_RESULTCODE_DENY_CHANNEL_IS_ASSOCIETED_WITH_ACTION_TRIGGER \ + 30 // ver. >= 16 + +#define SUPLA_OAUTH_RESULTCODE_ERROR 0 // ver. >= 10 +#define SUPLA_OAUTH_RESULTCODE_SUCCESS 1 // ver. >= 10 +#define SUPLA_OAUTH_TEMPORARILY_UNAVAILABLE 2 // ver. >= 10 + +#define SUPLA_DEVICE_NAME_MAXSIZE 201 +#define SUPLA_CLIENT_NAME_MAXSIZE 201 +#define SUPLA_SENDER_NAME_MAXSIZE 201 + +#ifdef __AVR__ +#ifdef __AVR_ATmega2560__ +#define SUPLA_CHANNELMAXCOUNT 32 +#else +#define SUPLA_CHANNELMAXCOUNT 1 +#endif +#else +#define SUPLA_CHANNELMAXCOUNT 128 +#endif + +#define SUPLA_CHANNELVALUE_SIZE 8 + +#ifdef __AVR__ +#define SUPLA_CHANNELEXTENDEDVALUE_SIZE 256 +#else +#define SUPLA_CHANNELEXTENDEDVALUE_SIZE 1024 +#endif + +#define SUPLA_CHANNELTYPE_SENSORNO 1000 +#define SUPLA_CHANNELTYPE_SENSORNC 1010 // DEPRECATED +#define SUPLA_CHANNELTYPE_DISTANCESENSOR 1020 // ver. >= 5 +#define SUPLA_CHANNELTYPE_CALLBUTTON 1500 // ver. >= 4 +#define SUPLA_CHANNELTYPE_RELAYHFD4 2000 +#define SUPLA_CHANNELTYPE_RELAYG5LA1A 2010 +#define SUPLA_CHANNELTYPE_2XRELAYG5LA1A 2020 +#define SUPLA_CHANNELTYPE_RELAY 2900 +#define SUPLA_CHANNELTYPE_THERMOMETERDS18B20 3000 +#define SUPLA_CHANNELTYPE_DHT11 3010 // ver. >= 4 +#define SUPLA_CHANNELTYPE_DHT22 3020 // ver. >= 4 +#define SUPLA_CHANNELTYPE_DHT21 3022 // ver. >= 5 +#define SUPLA_CHANNELTYPE_AM2302 3030 // ver. >= 4 +#define SUPLA_CHANNELTYPE_AM2301 3032 // ver. >= 5 + +#define SUPLA_CHANNELTYPE_THERMOMETER 3034 // ver. >= 8 +#define SUPLA_CHANNELTYPE_HUMIDITYSENSOR 3036 // ver. >= 8 +#define SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR 3038 // ver. >= 8 +#define SUPLA_CHANNELTYPE_WINDSENSOR 3042 // ver. >= 8 +#define SUPLA_CHANNELTYPE_PRESSURESENSOR 3044 // ver. >= 8 +#define SUPLA_CHANNELTYPE_RAINSENSOR 3048 // ver. >= 8 +#define SUPLA_CHANNELTYPE_WEIGHTSENSOR 3050 // ver. >= 8 +#define SUPLA_CHANNELTYPE_WEATHER_STATION 3100 // ver. >= 8 + +#define SUPLA_CHANNELTYPE_DIMMER 4000 // ver. >= 4 +#define SUPLA_CHANNELTYPE_RGBLEDCONTROLLER 4010 // ver. >= 4 +#define SUPLA_CHANNELTYPE_DIMMERANDRGBLED 4020 // ver. >= 4 + +#define SUPLA_CHANNELTYPE_ELECTRICITY_METER 5000 // ver. >= 10 +#define SUPLA_CHANNELTYPE_IMPULSE_COUNTER 5010 // ver. >= 10 + +#define SUPLA_CHANNELTYPE_THERMOSTAT 6000 // ver. >= 11 +#define SUPLA_CHANNELTYPE_THERMOSTAT_HEATPOL_HOMEPLUS 6010 // ver. >= 11 + +#define SUPLA_CHANNELTYPE_VALVE_OPENCLOSE 7000 // ver. >= 12 +#define SUPLA_CHANNELTYPE_VALVE_PERCENTAGE 7010 // ver. >= 12 +#define SUPLA_CHANNELTYPE_BRIDGE 8000 // ver. >= 12 +#define SUPLA_CHANNELTYPE_GENERAL_PURPOSE_MEASUREMENT 9000 // ver. >= 12 +#define SUPLA_CHANNELTYPE_ENGINE 10000 // ver. >= 12 +#define SUPLA_CHANNELTYPE_ACTIONTRIGGER 11000 // ver. >= 16 +#define SUPLA_CHANNELTYPE_DIGIGLASS 12000 // ver. >= 12 + +#define SUPLA_CHANNELDRIVER_MCP23008 2 + +#define SUPLA_CHANNELFNC_NONE 0 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEGATEWAYLOCK 10 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEGATE 20 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEGARAGEDOOR 30 +#define SUPLA_CHANNELFNC_THERMOMETER 40 +#define SUPLA_CHANNELFNC_HUMIDITY 42 +#define SUPLA_CHANNELFNC_HUMIDITYANDTEMPERATURE 45 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_GATEWAY 50 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_GATE 60 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_GARAGEDOOR 70 +#define SUPLA_CHANNELFNC_NOLIQUIDSENSOR 80 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEDOORLOCK 90 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_DOOR 100 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEROLLERSHUTTER 110 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEROOFWINDOW 115 // ver. >= 13 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_ROLLERSHUTTER 120 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_ROOFWINDOW 125 // ver. >= 13 +#define SUPLA_CHANNELFNC_POWERSWITCH 130 +#define SUPLA_CHANNELFNC_LIGHTSWITCH 140 +#define SUPLA_CHANNELFNC_RING 150 +#define SUPLA_CHANNELFNC_ALARM 160 +#define SUPLA_CHANNELFNC_NOTIFICATION 170 +#define SUPLA_CHANNELFNC_DIMMER 180 +#define SUPLA_CHANNELFNC_RGBLIGHTING 190 +#define SUPLA_CHANNELFNC_DIMMERANDRGBLIGHTING 200 +#define SUPLA_CHANNELFNC_DEPTHSENSOR 210 // ver. >= 5 +#define SUPLA_CHANNELFNC_DISTANCESENSOR 220 // ver. >= 5 +#define SUPLA_CHANNELFNC_OPENINGSENSOR_WINDOW 230 // ver. >= 8 +#define SUPLA_CHANNELFNC_MAILSENSOR 240 // ver. >= 8 +#define SUPLA_CHANNELFNC_WINDSENSOR 250 // ver. >= 8 +#define SUPLA_CHANNELFNC_PRESSURESENSOR 260 // ver. >= 8 +#define SUPLA_CHANNELFNC_RAINSENSOR 270 // ver. >= 8 +#define SUPLA_CHANNELFNC_WEIGHTSENSOR 280 // ver. >= 8 +#define SUPLA_CHANNELFNC_WEATHER_STATION 290 // ver. >= 8 +#define SUPLA_CHANNELFNC_STAIRCASETIMER 300 // ver. >= 8 +#define SUPLA_CHANNELFNC_ELECTRICITY_METER 310 // ver. >= 10 +#define SUPLA_CHANNELFNC_IC_ELECTRICITY_METER 315 // ver. >= 12 +#define SUPLA_CHANNELFNC_IC_GAS_METER 320 // ver. >= 10 +#define SUPLA_CHANNELFNC_IC_WATER_METER 330 // ver. >= 10 +#define SUPLA_CHANNELFNC_IC_HEAT_METER 340 // ver. >= 10 +#define SUPLA_CHANNELFNC_THERMOSTAT 400 // ver. >= 11 +#define SUPLA_CHANNELFNC_THERMOSTAT_HEATPOL_HOMEPLUS 410 // ver. >= 11 +#define SUPLA_CHANNELFNC_VALVE_OPENCLOSE 500 // ver. >= 12 +#define SUPLA_CHANNELFNC_VALVE_PERCENTAGE 510 // ver. >= 12 +#define SUPLA_CHANNELFNC_GENERAL_PURPOSE_MEASUREMENT 520 // ver. >= 12 +#define SUPLA_CHANNELFNC_CONTROLLINGTHEENGINESPEED 600 // ver. >= 12 +#define SUPLA_CHANNELFNC_ACTIONTRIGGER 700 // ver. >= 16 +#define SUPLA_CHANNELFNC_DIGIGLASS_HORIZONTAL 800 // ver. >= 14 +#define SUPLA_CHANNELFNC_DIGIGLASS_VERTICAL 810 // ver. >= 14 + +#define SUPLA_BIT_FUNC_CONTROLLINGTHEGATEWAYLOCK 0x00000001 +#define SUPLA_BIT_FUNC_CONTROLLINGTHEGATE 0x00000002 +#define SUPLA_BIT_FUNC_CONTROLLINGTHEGARAGEDOOR 0x00000004 +#define SUPLA_BIT_FUNC_CONTROLLINGTHEDOORLOCK 0x00000008 +#define SUPLA_BIT_FUNC_CONTROLLINGTHEROLLERSHUTTER 0x00000010 +#define SUPLA_BIT_FUNC_POWERSWITCH 0x00000020 +#define SUPLA_BIT_FUNC_LIGHTSWITCH 0x00000040 +#define SUPLA_BIT_FUNC_STAIRCASETIMER 0x00000080 // ver. >= 8 +#define SUPLA_BIT_FUNC_THERMOMETER 0x00000100 // ver. >= 12 +#define SUPLA_BIT_FUNC_HUMIDITYANDTEMPERATURE 0x00000200 // ver. >= 12 +#define SUPLA_BIT_FUNC_HUMIDITY 0x00000400 // ver. >= 12 +#define SUPLA_BIT_FUNC_WINDSENSOR 0x00000800 // ver. >= 12 +#define SUPLA_BIT_FUNC_PRESSURESENSOR 0x00001000 // ver. >= 12 +#define SUPLA_BIT_FUNC_RAINSENSOR 0x00002000 // ver. >= 12 +#define SUPLA_BIT_FUNC_WEIGHTSENSOR 0x00004000 // ver. >= 12 +#define SUPLA_BIT_FUNC_CONTROLLINGTHEROOFWINDOW 0x00008000 // ver. >= 13 + +#define SUPLA_EVENT_CONTROLLINGTHEGATEWAYLOCK 10 +#define SUPLA_EVENT_CONTROLLINGTHEGATE 20 +#define SUPLA_EVENT_CONTROLLINGTHEGARAGEDOOR 30 +#define SUPLA_EVENT_CONTROLLINGTHEDOORLOCK 40 +#define SUPLA_EVENT_CONTROLLINGTHEROLLERSHUTTER 50 +#define SUPLA_EVENT_CONTROLLINGTHEROOFWINDOW 55 +#define SUPLA_EVENT_POWERONOFF 60 +#define SUPLA_EVENT_LIGHTONOFF 70 +#define SUPLA_EVENT_STAIRCASETIMERONOFF 80 // ver. >= 9 +#define SUPLA_EVENT_VALVEOPENCLOSE 90 // ver. >= 12 +#define SUPLA_EVENT_SET_BRIDGE_VALUE_FAILED 100 // ver. >= 12 + +#define SUPLA_URL_PROTO_HTTP 0x01 +#define SUPLA_URL_PROTO_HTTPS 0x02 + +#define SUPLA_PLATFORM_UNKNOWN 0 +#define SUPLA_PLATFORM_ESP8266 1 + +#define SUPLA_TARGET_CHANNEL 0 +#define SUPLA_TARGET_GROUP 1 +#define SUPLA_TARGET_IODEVICE 2 + +#define SUPLA_MFR_UNKNOWN 0 +#define SUPLA_MFR_ACSOFTWARE 1 +#define SUPLA_MFR_TRANSCOM 2 +#define SUPLA_MFR_LOGI 3 +#define SUPLA_MFR_ZAMEL 4 +#define SUPLA_MFR_NICE 5 +#define SUPLA_MFR_ITEAD 6 +#define SUPLA_MFR_DOYLETRATT 7 +#define SUPLA_MFR_HEATPOL 8 +#define SUPLA_MFR_FAKRO 9 +#define SUPLA_MFR_PEVEKO 10 +#define SUPLA_MFR_WEKTA 11 +#define SUPLA_MFR_STA_SYSTEM 12 +#define SUPLA_MFR_DGF 13 +#define SUPLA_MFR_COMELIT 14 + +#define SUPLA_CHANNEL_FLAG_ZWAVE_BRIDGE 0x0001 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_IR_BRIDGE 0x0002 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_RF_BRIDGE 0x0004 // ver. >= 12 +// Free bit for future use: 0x0008 +#define SUPLA_CHANNEL_FLAG_CHART_TYPE_BAR 0x0010 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_CHART_DS_TYPE_DIFFERENTAL 0x0020 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_CHART_INTERPOLATE_MEASUREMENTS 0x0040 // ver. >= 12 +// Free bits for future use: 0x0080, 0x0100, 0x0200, 0x0400, 0x0800 +#define SUPLA_CHANNEL_FLAG_RS_AUTO_CALIBRATION 0x1000 // ver. >= 15 +#define SUPLA_CHANNEL_FLAG_CALCFG_RESET_COUNTERS 0x2000 // ver. >= 15 +// Free bits for future use: 0x8000 +#define SUPLA_CHANNEL_FLAG_CALCFG_RECALIBRATE 0x4000 // ver. >= 15 +#define SUPLA_CHANNEL_FLAG_CHANNELSTATE 0x00010000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_PHASE1_UNSUPPORTED 0x00020000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_PHASE2_UNSUPPORTED 0x00040000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_PHASE3_UNSUPPORTED 0x00080000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_TIME_SETTING_NOT_AVAILABLE 0x00100000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_RSA_ENCRYPTED_PIN_REQUIRED 0x00200000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_OFFLINE_DURING_REGISTRATION 0x00400000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_ZIGBEE_BRIDGE 0x00800000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_COUNTDOWN_TIMER_SUPPORTED 0x01000000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_LIGHTSOURCELIFESPAN_SETTABLE \ + 0x02000000 // ver. >= 12 +#define SUPLA_CHANNEL_FLAG_POSSIBLE_SLEEP_MODE 0x04000000 // ver. >= 12 + +#pragma pack(push, 1) + +typedef struct { + char tag[SUPLA_TAG_SIZE]; + unsigned char version; + unsigned _supla_int_t rr_id; // Request/Response ID + unsigned _supla_int_t call_type; + unsigned _supla_int_t data_size; + char data[SUPLA_MAX_DATA_SIZE]; // Last variable in struct! +} TSuplaDataPacket; + +typedef struct { + // server -> device|client + unsigned char proto_version_min; + unsigned char proto_version; + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; +} TSDC_SuplaGetVersionResult; + +typedef struct { + // server -> device|client + unsigned char server_version_min; + unsigned char server_version; +} TSDC_SuplaVersionError; + +typedef struct { + // device|client -> server + struct _supla_timeval now; +} TDCS_SuplaPingServer; + +// Compatibility with ESP8266 +struct timeval_compat { + _supla_int_t tv_sec; + _supla_int_t tv_usec; +}; + +typedef struct { + // device|client -> server + struct timeval_compat now; +} TDCS_SuplaPingServer_COMPAT; + +typedef struct { + // server -> device|client + struct _supla_timeval now; +} TSDC_SuplaPingServerResult; + +typedef struct { + // device|client -> server + unsigned char activity_timeout; +} TDCS_SuplaSetActivityTimeout; + +typedef struct { + // server -> device|client + unsigned char activity_timeout; + unsigned char min; + unsigned char max; +} TSDC_SuplaSetActivityTimeoutResult; + +typedef struct { + char value[SUPLA_CHANNELVALUE_SIZE]; + char sub_value[SUPLA_CHANNELVALUE_SIZE]; // For example sensor value +} TSuplaChannelValue; + +typedef struct { + char value[SUPLA_CHANNELVALUE_SIZE]; + char sub_value[SUPLA_CHANNELVALUE_SIZE]; // For example sensor value + char sub_value_type; // SUBV_TYPE_ +} TSuplaChannelValue_B; + +#define SUBV_TYPE_NOT_SET_OR_OFFLINE 0 +#define SUBV_TYPE_SENSOR 1 +#define SUBV_TYPE_ELECTRICITY_MEASUREMENTS 2 +#define SUBV_TYPE_IC_MEASUREMENTS 3 + +#define EV_TYPE_NONE 0 +#ifdef USE_DEPRECATED_EMEV_V1 +#define EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1 10 +#endif /*USE_DEPRECATED_EMEV_V1*/ +#define EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2 12 +#define EV_TYPE_IMPULSE_COUNTER_DETAILS_V1 20 +#define EV_TYPE_THERMOSTAT_DETAILS_V1 30 +#define EV_TYPE_CHANNEL_STATE_V1 40 +#define EV_TYPE_TIMER_STATE_V1 50 +#define EV_TYPE_CHANNEL_AND_TIMER_STATE_V1 60 +#define EV_TYPE_MULTI_VALUE 100 + +#define CALCFG_TYPE_THERMOSTAT_DETAILS_V1 10 + +typedef struct { + char type; // EV_TYPE_ + unsigned _supla_int_t size; + char value[SUPLA_CHANNELEXTENDEDVALUE_SIZE]; // Last variable in struct! +} TSuplaChannelExtendedValue; // v. >= 10 + +typedef struct { + // server -> client + char EOL; // End Of List + _supla_int_t Id; + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_LOCATION_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaLocation; + +typedef struct { + // server -> client + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaLocation + items[SUPLA_LOCATIONPACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaLocationPack; + +typedef struct { + // device -> server + unsigned char Number; + _supla_int_t Type; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TDS_SuplaDeviceChannel; + +typedef struct { + // device -> server + + _supla_int_t LocationID; + char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + unsigned char channel_count; + TDS_SuplaDeviceChannel + channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! +} TDS_SuplaRegisterDevice; + +typedef struct { + // device -> server + + unsigned char Number; + _supla_int_t Type; + + _supla_int_t FuncList; + _supla_int_t Default; + + char value[SUPLA_CHANNELVALUE_SIZE]; +} TDS_SuplaDeviceChannel_B; // ver. >= 2 + +typedef struct { + unsigned char relatedChannelNumber; // ChannelNumber + 1. + unsigned _supla_int_t disablesLocalOperation; +} TActionTriggerProperties; + +typedef struct { + // device -> server + + unsigned char Number; + _supla_int_t Type; + + union { + _supla_int_t FuncList; + unsigned _supla_int_t ActionTriggerCaps; // ver. >= 16 + }; + + _supla_int_t Default; + _supla_int_t Flags; + + union { + char value[SUPLA_CHANNELVALUE_SIZE]; + TActionTriggerProperties actionTriggerProperties; // ver. >= 16 + }; +} TDS_SuplaDeviceChannel_C; // ver. >= 10 + +typedef struct { + // device -> server + + _supla_int_t LocationID; + char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + unsigned char channel_count; + TDS_SuplaDeviceChannel_B + channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! +} TDS_SuplaRegisterDevice_B; // ver. >= 2 + +typedef struct { + // device -> server + + _supla_int_t LocationID; + char LocationPWD[SUPLA_LOCATION_PWD_MAXSIZE]; // UTF8 + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; + + unsigned char channel_count; + TDS_SuplaDeviceChannel_B + channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! +} TDS_SuplaRegisterDevice_C; // ver. >= 6 + +typedef struct { + // device -> server + + char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 + char AuthKey[SUPLA_AUTHKEY_SIZE]; + + char GUID[SUPLA_GUID_SIZE]; + + char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; + + unsigned char channel_count; + TDS_SuplaDeviceChannel_B + channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! +} TDS_SuplaRegisterDevice_D; // ver. >= 7 + +typedef struct { + // device -> server + + char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 + char AuthKey[SUPLA_AUTHKEY_SIZE]; + + char GUID[SUPLA_GUID_SIZE]; + + char Name[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; + + _supla_int_t Flags; // SUPLA_DEVICE_FLAG_* + _supla_int16_t ManufacturerID; + _supla_int16_t ProductID; + + unsigned char channel_count; + TDS_SuplaDeviceChannel_C + channels[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! +} TDS_SuplaRegisterDevice_E; // ver. >= 10 + +typedef struct { + // server -> device + + _supla_int_t result_code; + unsigned char activity_timeout; + unsigned char version; + unsigned char version_min; +} TSD_SuplaRegisterDeviceResult; + +typedef struct { + // device -> server + + unsigned char ChannelNumber; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TDS_SuplaDeviceChannelValue; + +typedef struct { + // device -> server + + unsigned char ChannelNumber; + unsigned char Offline; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TDS_SuplaDeviceChannelValue_B; // v. >= 12 + +typedef struct { + // device -> server + + unsigned char ChannelNumber; + unsigned char Offline; + unsigned _supla_int_t ValidityTimeSec; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TDS_SuplaDeviceChannelValue_C; // v. >= 12 + +typedef struct { + // device -> server + + unsigned char ChannelNumber; + TSuplaChannelExtendedValue value; // Last variable in struct! +} TDS_SuplaDeviceChannelExtendedValue; // v. >= 10 + +typedef struct { + // server -> device + _supla_int_t SenderID; + unsigned char ChannelNumber; + unsigned _supla_int_t DurationMS; + + char value[SUPLA_CHANNELVALUE_SIZE]; +} TSD_SuplaChannelNewValue; + +typedef struct { + // server -> device + _supla_int_t SenderID; + _supla_int_t GroupID; + unsigned char EOL; // End Of List + unsigned char ChannelNumber; + unsigned _supla_int_t DurationMS; + + char value[SUPLA_CHANNELVALUE_SIZE]; +} TSD_SuplaChannelGroupNewValue; // v. >= 13 + +typedef struct { + // device -> server + unsigned char ChannelNumber; + _supla_int_t SenderID; + char Success; +} TDS_SuplaChannelNewValueResult; + +typedef struct { + // server -> client + + char EOL; // End Of List + _supla_int_t Id; + char online; + + TSuplaChannelValue value; +} TSC_SuplaChannelValue; + +typedef struct { + // server -> client + + char EOL; // End Of List + _supla_int_t Id; + char online; + + TSuplaChannelValue_B value; +} TSC_SuplaChannelValue_B; // ver. >= 15 + +typedef struct { + // server -> client + _supla_int_t Id; + + TSuplaChannelExtendedValue value; // Last variable in struct! +} TSC_SuplaChannelExtendedValue; + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + + TSC_SuplaChannelValue + items[SUPLA_CHANNELVALUE_PACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelValuePack; // ver. >= 9 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + + TSC_SuplaChannelValue_B + items[SUPLA_CHANNELVALUE_PACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelValuePack_B; // ver. >= 15 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + unsigned _supla_int_t pack_size; + + char pack[SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE]; // Last variable in + // struct! +} TSC_SuplaChannelExtendedValuePack; // ver. >= 10 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t LocationID; + _supla_int_t Func; + char online; + + TSuplaChannelValue value; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannel; + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannel + items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelPack; + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t LocationID; + _supla_int_t Func; + _supla_int_t AltIcon; + unsigned _supla_int_t Flags; + unsigned char ProtocolVersion; + char online; + + TSuplaChannelValue value; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannel_B; // ver. >= 8 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannel_B + items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelPack_B; // ver. >= 8 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t DeviceID; + _supla_int_t LocationID; + _supla_int_t Type; + _supla_int_t Func; + _supla_int_t AltIcon; + _supla_int_t UserIcon; + _supla_int16_t ManufacturerID; + _supla_int16_t ProductID; + + unsigned _supla_int_t Flags; + unsigned char ProtocolVersion; + char online; + + TSuplaChannelValue value; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannel_C; // ver. >= 10 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t DeviceID; + _supla_int_t LocationID; + _supla_int_t Type; + _supla_int_t Func; + _supla_int_t AltIcon; + _supla_int_t UserIcon; + _supla_int16_t ManufacturerID; + _supla_int16_t ProductID; + + unsigned _supla_int_t Flags; + unsigned char ProtocolVersion; + char online; + + TSuplaChannelValue_B value; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannel_D; // ver. >= 15 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannel_C + items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelPack_C; // ver. >= 10 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannel_D + items[SUPLA_CHANNELPACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelPack_D; // ver. >= 15 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t LocationID; + _supla_int_t Func; + _supla_int_t AltIcon; + unsigned _supla_int_t Flags; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNELGROUP_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannelGroup; // ver. >= 9 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t Id; + _supla_int_t LocationID; + _supla_int_t Func; + _supla_int_t AltIcon; + _supla_int_t UserIcon; + unsigned _supla_int_t Flags; + + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNELGROUP_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SuplaChannelGroup_B; // ver. >= 10 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannelGroup + items[SUPLA_CHANNELGROUP_PACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelGroupPack; // ver. >= 9 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannelGroup_B + items[SUPLA_CHANNELGROUP_PACK_MAXCOUNT]; // Last variable in struct! +} TSC_SuplaChannelGroupPack_B; // ver. >= 10 + +typedef struct { + // server -> client + char EOL; // End Of List + + _supla_int_t ChannelGroupID; + _supla_int_t ChannelID; +} TSC_SuplaChannelGroupRelation; // ver. >= 9 + +typedef struct { + // server -> client + + _supla_int_t count; + _supla_int_t total_left; + TSC_SuplaChannelGroupRelation + items[SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT]; // Last variable in + // struct! +} TSC_SuplaChannelGroupRelationPack; // ver. >= 9 + +typedef struct { + // client -> server + + _supla_int_t AccessID; + char AccessIDpwd[SUPLA_ACCESSID_PWD_MAXSIZE]; // UTF8 + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; +} TCS_SuplaRegisterClient; + +typedef struct { + // client -> server + + _supla_int_t AccessID; + char AccessIDpwd[SUPLA_ACCESSID_PWD_MAXSIZE]; // UTF8 + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; +} TCS_SuplaRegisterClient_B; // ver. >= 6 + +typedef struct { + // client -> server + + char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 + char AuthKey[SUPLA_AUTHKEY_SIZE]; + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; +} TCS_SuplaRegisterClient_C; // ver. >= 7 + +typedef struct { + // client -> server + + char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 + char Password[SUPLA_PASSWORD_MAXSIZE]; // Optional - UTF8 + char AuthKey[SUPLA_AUTHKEY_SIZE]; + + char GUID[SUPLA_GUID_SIZE]; + char Name[SUPLA_CLIENT_NAME_MAXSIZE]; // UTF8 + char SoftVer[SUPLA_SOFTVER_MAXSIZE]; + + char ServerName[SUPLA_SERVER_NAME_MAXSIZE]; +} TCS_SuplaRegisterClient_D; // ver. >= 12 + +typedef struct { + // server -> client + + _supla_int_t result_code; + _supla_int_t ClientID; + _supla_int_t LocationCount; + _supla_int_t ChannelCount; + unsigned char activity_timeout; + unsigned char version; + unsigned char version_min; +} TSC_SuplaRegisterClientResult; + +typedef struct { + // server -> client + + _supla_int_t result_code; + _supla_int_t ClientID; + _supla_int_t LocationCount; + _supla_int_t ChannelCount; + _supla_int_t ChannelGroupCount; + _supla_int_t Flags; + unsigned char activity_timeout; + unsigned char version; + unsigned char version_min; +} TSC_SuplaRegisterClientResult_B; // ver. >= 9 + +typedef struct { + // server -> client + + _supla_int_t result_code; + _supla_int_t ClientID; + _supla_int_t LocationCount; + _supla_int_t ChannelCount; + _supla_int_t ChannelGroupCount; + _supla_int_t Flags; + unsigned char activity_timeout; + unsigned char version; + unsigned char version_min; + unsigned _supla_int_t serverUnixTimestamp; // current server time +} TSC_SuplaRegisterClientResult_C; // ver. >= 17 + +typedef struct { + // client -> server + unsigned char ChannelId; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TCS_SuplaChannelNewValue; // Deprecated + +typedef struct { + // client -> server + _supla_int_t ChannelId; + char value[SUPLA_CHANNELVALUE_SIZE]; +} TCS_SuplaChannelNewValue_B; + +typedef struct { + // client -> server + _supla_int_t Id; + char Target; // SUPLA_TARGET_ + char value[SUPLA_CHANNELVALUE_SIZE]; +} TCS_SuplaNewValue; // ver. >= 9 + +typedef struct { + // server -> client + _supla_int_t Event; + _supla_int_t ChannelID; + unsigned _supla_int_t DurationMS; + + _supla_int_t SenderID; + unsigned _supla_int_t + SenderNameSize; // including the terminating null byte ('\0') + char + SenderName[SUPLA_SENDER_NAME_MAXSIZE]; // Last variable in struct! | UTF8 +} TSC_SuplaEvent; + +typedef struct { + char Platform; + + _supla_int_t Param1; + _supla_int_t Param2; + _supla_int_t Param3; + _supla_int_t Param4; +} TDS_FirmwareUpdateParams; + +typedef struct { + char available_protocols; + char host[SUPLA_URL_HOST_MAXSIZE]; + _supla_int_t port; + char path[SUPLA_URL_PATH_MAXSIZE]; +} TSD_FirmwareUpdate_Url; + +typedef struct { + char exists; + TSD_FirmwareUpdate_Url url; +} TSD_FirmwareUpdate_UrlResult; + +typedef struct { + unsigned _supla_int_t client_timestamp; // time >= now == enabled + unsigned _supla_int_t iodevice_timestamp; // time >= now == enabled +} TSDC_RegistrationEnabled; + +typedef struct { + unsigned _supla_int_t ExpiresIn; + unsigned _supla_int_t + TokenSize; // including the terminating null byte ('\0') + char Token[SUPLA_OAUTH_TOKEN_MAXSIZE]; // Last variable in struct! +} TSC_OAuthToken; // ver. >= 10 + +typedef struct { + unsigned char ResultCode; + TSC_OAuthToken Token; +} TSC_OAuthTokenRequestResult; // ver. >= 10 + +typedef struct { + // 3 phases + unsigned _supla_int16_t freq; // * 0.01 Hz + unsigned _supla_int16_t voltage[3]; // * 0.01 V + unsigned _supla_int16_t + current[3]; // * 0.001 A (0.01A FOR EM_VAR_CURRENT_OVER_65A) + _supla_int_t power_active[3]; // * 0.00001 W or kW + _supla_int_t power_reactive[3]; // * 0.00001 var or kvar + _supla_int_t power_apparent[3]; // * 0.00001 VA or kVA + _supla_int16_t power_factor[3]; // * 0.001 + _supla_int16_t phase_angle[3]; // * 0.1 degree +} TElectricityMeter_Measurement; // v. >= 10 + +#define EM_VAR_FREQ 0x0001 +#define EM_VAR_VOLTAGE 0x0002 +#define EM_VAR_CURRENT 0x0004 +#define EM_VAR_POWER_ACTIVE 0x0008 +#define EM_VAR_POWER_REACTIVE 0x0010 +#define EM_VAR_POWER_APPARENT 0x0020 +#define EM_VAR_POWER_FACTOR 0x0040 +#define EM_VAR_PHASE_ANGLE 0x0080 +#define EM_VAR_FORWARD_ACTIVE_ENERGY 0x0100 +#define EM_VAR_REVERSE_ACTIVE_ENERGY 0x0200 +#define EM_VAR_FORWARD_REACTIVE_ENERGY 0x0400 +#define EM_VAR_REVERSE_REACTIVE_ENERGY 0x0800 +#define EM_VAR_CURRENT_OVER_65A 0x1000 +#define EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED 0x2000 +#define EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED 0x4000 +#define EM_VAR_ALL 0xFFFF + +#define EM_VAR_POWER_ACTIVE_KWH 0x100000 +#define EM_VAR_POWER_REACTIVE_KVAR 0x200000 +#define EM_VAR_POWER_APPARENT_KVA 0x400000 + +#ifdef __AVR__ +#define EM_MEASUREMENT_COUNT 1 +#else +#define EM_MEASUREMENT_COUNT 5 +#endif + +#ifdef USE_DEPRECATED_EMEV_V1 +// [IODevice->Server->Client] +typedef struct { + unsigned _supla_int64_t total_forward_active_energy[3]; // * 0.00001 kWh + unsigned _supla_int64_t total_reverse_active_energy[3]; // * 0.00001 kWh + unsigned _supla_int64_t total_forward_reactive_energy[3]; // * 0.00001 kvarh + unsigned _supla_int64_t total_reverse_reactive_energy[3]; // * 0.00001 kvarh + + // The price per unit, total cost and currency is overwritten by the server + // total_cost == SUM(total_forward_active_energy[n] * price_per_unit + _supla_int_t total_cost; // * 0.01 + _supla_int_t price_per_unit; // * 0.0001 + // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm + char currency[3]; + + _supla_int_t measured_values; + _supla_int_t period; // Approximate period between measurements in seconds + _supla_int_t m_count; + TElectricityMeter_Measurement m[EM_MEASUREMENT_COUNT]; // Last variable in + // struct! +} TElectricityMeter_ExtendedValue; // v. >= 10 +#endif /*USE_DEPRECATED_EMEV_V1*/ + +// [IODevice->Server->Client] +typedef struct { + unsigned _supla_int64_t total_forward_active_energy[3]; // * 0.00001 kWh + unsigned _supla_int64_t total_reverse_active_energy[3]; // * 0.00001 kWh + unsigned _supla_int64_t total_forward_reactive_energy[3]; // * 0.00001 kvarh + unsigned _supla_int64_t total_reverse_reactive_energy[3]; // * 0.00001 kvarh + unsigned _supla_int64_t + total_forward_active_energy_balanced; // * 0.00001 kWh + // Vector phase-to-phase balancing + unsigned _supla_int64_t + total_reverse_active_energy_balanced; // * 0.00001 kWh + // Vector phase-to-phase balancing + + // The price per unit, total cost and currency is overwritten by the server + // total_cost == SUM(total_forward_active_energy[n] * price_per_unit + _supla_int_t total_cost; // * 0.01 + _supla_int_t total_cost_balanced; // * 0.01 + _supla_int_t price_per_unit; // * 0.0001 + // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm + char currency[3]; + + _supla_int_t measured_values; + _supla_int_t period; // Approximate period between measurements in seconds + _supla_int_t m_count; + TElectricityMeter_Measurement m[EM_MEASUREMENT_COUNT]; // Last variable in + // struct! +} TElectricityMeter_ExtendedValue_V2; // v. >= 12 + +#define EM_VALUE_FLAG_PHASE1_ON 0x01 +#define EM_VALUE_FLAG_PHASE2_ON 0x02 +#define EM_VALUE_FLAG_PHASE3_ON 0x04 + +// [IODevice->Server->Client] +typedef struct { + char flags; + unsigned _supla_int_t total_forward_active_energy; // * 0.01 kW +} TElectricityMeter_Value; // v. >= 10 + +typedef struct { + // The price per unit, total cost and currency is overwritten by the server + // total_cost = calculated_value * price_per_unit + _supla_int_t total_cost; // * 0.01 + _supla_int_t price_per_unit; // * 0.0001 + // Currency Code A https://www.nationsonline.org/oneworld/currencies.htm + char currency[3]; + char custom_unit[9]; // UTF8 including the terminating null byte ('\0') + + _supla_int_t impulses_per_unit; + unsigned _supla_int64_t counter; + _supla_int64_t calculated_value; // * 0.001 +} TSC_ImpulseCounter_ExtendedValue; // v. >= 10 + +typedef struct { + unsigned _supla_int64_t counter; +} TDS_ImpulseCounter_Value; + +#define RS_VALUE_FLAG_TILT_IS_SET 0x1 +#define RS_VALUE_FLAG_CALIBRATION_FAILED 0x2 +#define RS_VALUE_FLAG_CALIBRATION_LOST 0x4 +#define RS_VALUE_FLAG_MOTOR_PROBLEM 0x8 +#define RS_VALUE_FLAG_CALIBRATION_IN_PROGRESS 0x10 + +typedef struct { + char position; // -1 == calibration. -1 - 100% + char tilt; + char bottom_position; // Percentage points to the windowsill + _supla_int16_t flags; +} TRollerShutterValue; + +typedef struct { + unsigned _supla_int64_t calculated_value; // * 0.001 +} TSC_ImpulseCounter_Value; // v. >= 10 + +typedef struct { + char Email[SUPLA_EMAIL_MAXSIZE]; // UTF8 + char Password[SUPLA_PASSWORD_MAXSIZE]; // UTF8 +} TCS_SuperUserAuthorizationRequest; // v. >= 10 + +typedef struct { + _supla_int_t Result; +} TSC_SuperUserAuthorizationResult; // v. >= 10 + +#define SUPLA_CALCFG_RESULT_FALSE 0 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_TRUE 1 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_DONE 2 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_IN_PROGRESS 3 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_NODE_FOUND 4 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_SENDER_CONFLICT 100 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_TIMEOUT 101 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_NOT_SUPPORTED 102 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_ID_NOT_EXISTS 103 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_UNAUTHORIZED 104 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_DEBUG 105 // ver. >= 12 +#define SUPLA_CALCFG_RESULT_NOT_SUPPORTED_IN_SLAVE_MODE 106 // ver. >= 12 + +#define SUPLA_CALCFG_CMD_GET_CHANNEL_FUNCLIST 1000 // v. >= 11 +#define SUPLA_CALCFG_CMD_CANCEL_ALL_CLIENT_COMMANDS 1010 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_RESET_AND_CLEAR 2000 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_ADD_NODE 2010 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_REMOVE_NODE 2020 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_GET_NODE_LIST 2030 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_GET_ASSIGNED_NODE_ID 2040 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_ASSIGN_NODE_ID 2050 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_GET_WAKE_UP_SETTINGS 2060 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_SET_WAKE_UP_TIME 2070 // v. >= 12 +#define SUPLA_CALCFG_CMD_ZWAVE_CONFIG_MODE_ACTIVE 4000 // v. >= 12 +#define SUPLA_CALCFG_CMD_DEBUG_STRING 5000 // v. >= 12 +#define SUPLA_CALCFG_CMD_PROGRESS_REPORT 5001 // v. >= 12 +#define SUPLA_CALCFG_CMD_SET_LIGHTSOURCE_LIFESPAN 6000 // v. >= 12 +#define SUPLA_CALCFG_CMD_RESET_COUNTERS 7000 // v. >= 15 +#define SUPLA_CALCFG_CMD_RECALIBRATE 8000 // v. >= 15 + +#define SUPLA_CALCFG_DATATYPE_RS_SETTINGS 1000 + +#define CALCFG_ZWAVE_SCREENTYPE_UNKNOWN 0 +#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL 1 +#define CALCFG_ZWAVE_SCREENTYPE_BINARY 2 +#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL_AUTOSHADE 3 +#define CALCFG_ZWAVE_SCREENTYPE_MULTILEVEL_COLOR_CONTROL 4 +#define CALCFG_ZWAVE_SCREENTYPE_BINARY_COLOR_CONTROL 5 +#define CALCFG_ZWAVE_SCREENTYPE_SENSOR 6 + +#define ZWAVE_NODE_NAME_MAXSIZE 50 + +#define ZWAVE_NODE_FLAG_CHANNEL_ASSIGNED 0x1 +#define ZWAVE_NODE_FLAG_WAKEUP_TIME_SETTABLE 0x2 + +typedef struct { + unsigned char Id; + unsigned char Flags; + union { + unsigned char ChannelNumber; + _supla_int_t ChannelID; + }; + unsigned char ScreenType; + unsigned char NameSize; // including the terminating null byte ('\0') + char Name[ZWAVE_NODE_NAME_MAXSIZE]; // UTF8. Last variable in struct! +} TCalCfg_ZWave_Node; // v. >= 12 + +typedef struct { + unsigned _supla_int_t MinimumSec : 24; + unsigned _supla_int_t MaximumSec : 24; + unsigned _supla_int_t ValueSec : 24; + unsigned _supla_int_t IntervalStepSec : 24; +} TCalCfg_ZWave_WakeupSettingsReport; + +typedef struct { + unsigned _supla_int_t TimeSec : 24; +} TCalCfg_ZWave_WakeUpTime; + +typedef struct { + _supla_int_t Command; + unsigned char Progress; // 0 - 100% +} TCalCfg_ProgressReport; + +typedef struct { + unsigned char ResetCounter; // 0 - NO, 1 - YES + unsigned char SetTime; // 0 - NO, 1 - YES + unsigned short LightSourceLifespan; // 0 - 65535 hours +} TCalCfg_LightSourceLifespan; + +// CALCFG == CALIBRATION / CONFIG +typedef struct { + _supla_int_t ChannelID; + _supla_int_t Command; + _supla_int_t DataType; + unsigned _supla_int_t DataSize; + char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! +} TCS_DeviceCalCfgRequest; // v. >= 10 + +// CALCFG == CALIBRATION / CONFIG +typedef struct { + _supla_int_t Id; + char Target; // SUPLA_TARGET_ + _supla_int_t Command; + _supla_int_t DataType; + unsigned _supla_int_t DataSize; + char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! +} TCS_DeviceCalCfgRequest_B; // v. >= 11 + +typedef struct { + _supla_int_t ChannelID; + _supla_int_t Command; + _supla_int_t Result; + unsigned _supla_int_t DataSize; + char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! +} TSC_DeviceCalCfgResult; // v. >= 10 + +typedef struct { + _supla_int_t SenderID; + _supla_int_t ChannelNumber; + _supla_int_t Command; + char SuperUserAuthorized; + _supla_int_t DataType; + unsigned _supla_int_t DataSize; + char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! +} TSD_DeviceCalCfgRequest; // v. >= 10 + +typedef struct { + _supla_int_t ReceiverID; + _supla_int_t ChannelNumber; + _supla_int_t Command; + _supla_int_t Result; + unsigned _supla_int_t DataSize; + char Data[SUPLA_CALCFG_DATA_MAXSIZE]; // Last variable in struct! +} TDS_DeviceCalCfgResult; // v. >= 10 + +typedef struct { + _supla_int_t FullOpeningTimeMS; + _supla_int_t FullClosingTimeMS; +} TCalCfg_RollerShutterSettings; + +#define RGBW_BRIGHTNESS_ONOFF 0x1 +#define RGBW_COLOR_ONOFF 0x2 + +typedef struct { + char brightness; + char colorBrightness; + char B; + char G; + char R; + char onOff; +} TRGBW_Value; // v. >= 10 + +#define SUPLA_RELAY_FLAG_OVERCURRENT_RELAY_OFF 0x1 + +typedef struct { + char hi; // actual state of relay - 0 turned off, >= 1 - turned on + unsigned short flags; // SUPLA_RELAY_FLAG_* +} TRelayChannel_Value; // v. >= 15 + +#define DIGIGLASS_TOO_LONG_OPERATION_WARNING 0x1 +#define DIGIGLASS_PLANNED_REGENERATION_IN_PROGRESS 0x2 +#define DIGIGLASS_REGENERATION_AFTER_20H_IN_PROGRESS 0x4 + +typedef struct { + unsigned char flags; + unsigned char sectionCount; // 1 - 16 Filled by server + unsigned short mask; // bit mask. 0 - opaque, 1 - transparent +} TDigiglass_Value; // v. >= 14 + +typedef struct { + unsigned short mask; // Bit mask. 0 - opaque, 1 - transparent + unsigned short + active_bits; // Specifies which bits of the mask are not skipped +} TCSD_Digiglass_NewValue; // v. >= 14 + +typedef struct { + unsigned char sec; // 0-59 + unsigned char min; // 0-59 + unsigned char hour; // 0-24 + unsigned char dayOfWeek; // 1 = Sunday, 2 = Monday, …, 7 = Saturday +} TThermostat_Time; // v. >= 11 + +#define THERMOSTAT_SCHEDULE_DAY_SUNDAY 0x01 +#define THERMOSTAT_SCHEDULE_DAY_MONDAY 0x02 +#define THERMOSTAT_SCHEDULE_DAY_TUESDAY 0x04 +#define THERMOSTAT_SCHEDULE_DAY_WEDNESDAY 0x08 +#define THERMOSTAT_SCHEDULE_DAY_THURSDAY 0x10 +#define THERMOSTAT_SCHEDULE_DAY_FRIDAY 0x20 +#define THERMOSTAT_SCHEDULE_DAY_SATURDAY 0x40 +#define THERMOSTAT_SCHEDULE_DAY_ALL 0xFF + +#define THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_TEMPERATURE 0 +#define THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_PROGRAM 1 + +typedef struct { + unsigned char ValueType; // THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_ + char HourValue[7][24]; // 7 days x 24h + // 0 = Sunday, 1 = Monday, …, 6 = Saturday +} TThermostat_Schedule; // v. >= 11 + +typedef struct { + unsigned char ValueType; // THERMOSTAT_SCHEDULE_HOURVALUE_TYPE_ + unsigned char WeekDays; // THERMOSTAT_SCHEDULE_DAY_ + char HourValue[24]; +} TThermostatValueGroup; // v. >= 11 + +typedef struct { + TThermostatValueGroup Group[4]; +} TThermostat_ScheduleCfg; // v. >= 11 + +#define TEMPERATURE_INDEX1 0x0001 +#define TEMPERATURE_INDEX2 0x0002 +#define TEMPERATURE_INDEX3 0x0004 +#define TEMPERATURE_INDEX4 0x0008 +#define TEMPERATURE_INDEX5 0x0010 +#define TEMPERATURE_INDEX6 0x0020 +#define TEMPERATURE_INDEX7 0x0040 +#define TEMPERATURE_INDEX8 0x0080 +#define TEMPERATURE_INDEX9 0x0100 +#define TEMPERATURE_INDEX10 0x0200 + +typedef struct { + _supla_int16_t Index; // BIT0 Temperature[0], BIT1 Temperature[1] etc... + unsigned _supla_int16_t Temperature[10]; +} TThermostatTemperatureCfg; + +// Thermostat configuration commands - ver. >= 11 +#define SUPLA_THERMOSTAT_CMD_TURNON 1 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_AUTO 2 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_COOL 3 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_HEAT 4 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_NORMAL 5 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_ECO 6 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_TURBO 7 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_DRY 8 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_FANONLY 9 +#define SUPLA_THERMOSTAT_CMD_SET_MODE_PURIFIER 10 +#define SUPLA_THERMOSTAT_CMD_SET_SCHEDULE 11 +#define SUPLA_THERMOSTAT_CMD_SET_TIME 12 +#define SUPLA_THERMOSTAT_CMD_SET_TEMPERATURE 13 + +// Thermostat capability flags - ver. >= 11 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_ONOFF 0x0001 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_AUTO 0x0002 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_COOL 0x0004 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_HEAT 0x0008 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_ECO 0x0010 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_DRY 0x0020 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_FANONLY 0x0040 +#define SUPLA_THERMOSTAT_CAP_FLAG_MODE_PURIFIER 0x0080 +#define SUPLA_THERMOSTAT_CAP_FLAG_SCHEDULE 0x0100 + +// Thermostat value flags - ver. >= 11 +#define SUPLA_THERMOSTAT_VALUE_FLAG_ON 0x0001 +#define SUPLA_THERMOSTAT_VALUE_FLAG_AUTO_MODE 0x0002 +#define SUPLA_THERMOSTAT_VALUE_FLAG_COOL_MODE 0x0004 +#define SUPLA_THERMOSTAT_VALUE_FLAG_HEAT_MODE 0x0008 +#define SUPLA_THERMOSTAT_VALUE_FLAG_ECO_MODE 0x0010 +#define SUPLA_THERMOSTAT_VALUE_FLAG_DRY_MODE 0x0020 +#define SUPLA_THERMOSTAT_VALUE_FLAG_FANONLY_MODE 0x0040 +#define SUPLA_THERMOSTAT_VALUE_FLAG_PURIFIER_MODE 0x0080 + +// Thermostat fields - ver. >= 11 +#define THERMOSTAT_FIELD_MeasuredTemperatures 0x01 +#define THERMOSTAT_FIELD_PresetTemperatures 0x02 +#define THERMOSTAT_FIELD_Flags 0x04 +#define THERMOSTAT_FIELD_Values 0x08 +#define THERMOSTAT_FIELD_Time 0x10 +#define THERMOSTAT_FIELD_Schedule 0x20 + +typedef struct { + unsigned char Fields; + _supla_int16_t MeasuredTemperature[10]; // * 0.01 + _supla_int16_t PresetTemperature[10]; // * 0.01 + _supla_int16_t Flags[8]; + _supla_int16_t Values[8]; + TThermostat_Time Time; + TThermostat_Schedule Schedule; // 7 days x 24h (4bit/hour) +} TThermostat_ExtendedValue; // v. >= 11 + +typedef struct { + unsigned char IsOn; + unsigned char Flags; + _supla_int16_t MeasuredTemperature; // * 0.01 + _supla_int16_t PresetTemperature; // * 0.01 +} TThermostat_Value; // v. >= 11 + +typedef struct { + unsigned _supla_int16_t year; + unsigned char month; + unsigned char day; + unsigned char dayOfWeek; // 1 = Sunday, 2 = Monday, …, 7 = Saturday + unsigned char hour; + unsigned char min; + unsigned char sec; + unsigned _supla_int_t + timezoneSize; // including the terminating null byte ('\0') + char timezone[SUPLA_TIMEZONE_MAXSIZE]; // Last variable in struct! +} TSDC_UserLocalTimeResult; + +typedef struct { + _supla_int_t SenderID; + union { + _supla_int_t ChannelID; // Client -> Server + unsigned char ChannelNumber; // Server -> Device + }; +} TCSD_ChannelStateRequest; // v. >= 12 Client -> Server -> Device + +#define SUPLA_CHANNELSTATE_FIELD_IPV4 0x0001 +#define SUPLA_CHANNELSTATE_FIELD_MAC 0x0002 +#define SUPLA_CHANNELSTATE_FIELD_BATTERYLEVEL 0x0004 +#define SUPLA_CHANNELSTATE_FIELD_BATTERYPOWERED 0x0008 +#define SUPLA_CHANNELSTATE_FIELD_WIFIRSSI 0x0010 +#define SUPLA_CHANNELSTATE_FIELD_WIFISIGNALSTRENGTH 0x0020 +#define SUPLA_CHANNELSTATE_FIELD_BRIDGENODESIGNALSTRENGTH 0x0040 +#define SUPLA_CHANNELSTATE_FIELD_UPTIME 0x0080 +#define SUPLA_CHANNELSTATE_FIELD_CONNECTIONUPTIME 0x0100 +#define SUPLA_CHANNELSTATE_FIELD_BATTERYHEALTH 0x0200 +#define SUPLA_CHANNELSTATE_FIELD_BRIDGENODEONLINE 0x0400 +#define SUPLA_CHANNELSTATE_FIELD_LASTCONNECTIONRESETCAUSE 0x0800 +#define SUPLA_CHANNELSTATE_FIELD_LIGHTSOURCELIFESPAN 0x1000 +#define SUPLA_CHANNELSTATE_FIELD_LIGHTSOURCEOPERATINGTIME 0x2000 + +#define SUPLA_LASTCONNECTIONRESETCAUSE_UNKNOWN 0 +#define SUPLA_LASTCONNECTIONRESETCAUSE_ACTIVITY_TIMEOUT 1 +#define SUPLA_LASTCONNECTIONRESETCAUSE_WIFI_CONNECTION_LOST 2 +#define SUPLA_LASTCONNECTIONRESETCAUSE_SERVER_CONNECTION_LOST 3 + +typedef struct { + _supla_int_t ReceiverID; // Not used in extended values + union { + // Not used in extended values + _supla_int_t ChannelID; // Server -> Client + unsigned char ChannelNumber; // Device -> Server + }; + _supla_int_t Fields; + _supla_int_t defaultIconField; // SUPLA_CHANNELSTATE_FIELD_* + unsigned _supla_int_t IPv4; + unsigned char MAC[6]; + unsigned char BatteryLevel; // 0 - 100% + unsigned char BatteryPowered; // true(1)/false(0) + char WiFiRSSI; + unsigned char WiFiSignalStrength; // 0 - 100% + unsigned char BridgeNodeOnline; // 0/1 + unsigned char BridgeNodeSignalStrength; // 0 - 100% + unsigned _supla_int_t Uptime; // sec. + unsigned _supla_int_t ConnectionUptime; // sec. + unsigned char BatteryHealth; + unsigned char LastConnectionResetCause; // SUPLA_LASTCONNECTIONRESETCAUSE_* + unsigned short LightSourceLifespan; // 0 - 65535 hours + union { + short LightSourceLifespanLeft; // -327,67 - 100.00% LightSourceLifespan * + // 0.01 + _supla_int_t LightSourceOperatingTime; // -3932100sec. - 3932100sec. + }; + char EmptySpace[2]; // Empty space for future use +} TDSC_ChannelState; // v. >= 12 Device -> Server -> Client + +#define TChannelState_ExtendedValue TDSC_ChannelState + +typedef struct { + _supla_int_t ChannelID; +} TCS_ChannelBasicCfgRequest; // v. >= 12 + +typedef struct { + union { + // Remaining time to turn off + unsigned _supla_int_t RemainingTimeMs; + unsigned _supla_int_t CountdownEndsAt; // Unix timestamp - Filled by server + }; + + unsigned char TargetValue[SUPLA_CHANNELVALUE_SIZE]; + + _supla_int_t SenderID; + unsigned _supla_int_t + SenderNameSize; // including the terminating null byte ('\0') + char SenderName[SUPLA_SENDER_NAME_MAXSIZE]; // Last variable in struct! + // UTF8 | Filled by server +} TTimerState_ExtendedValue; + +typedef struct { + TChannelState_ExtendedValue Channel; + TTimerState_ExtendedValue Timer; // Last variable in struct! +} TChannelAndTimerState_ExtendedValue; + +typedef struct { + char DeviceName[SUPLA_DEVICE_NAME_MAXSIZE]; // UTF8 + char DeviceSoftVer[SUPLA_SOFTVER_MAXSIZE]; + _supla_int_t DeviceID; + _supla_int_t DeviceFlags; + _supla_int16_t ManufacturerID; + _supla_int16_t ProductID; + + _supla_int_t ID; + unsigned char Number; + _supla_int_t Type; + _supla_int_t Func; + _supla_int_t FuncList; + + unsigned _supla_int_t ChannelFlags; + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CHANNEL_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_ChannelBasicCfg; // v. >= 12 + +typedef struct { + _supla_int_t ChannelID; + _supla_int_t Func; +} TCS_SetChannelFunction; // v. >= 12 + +typedef struct { + _supla_int_t ChannelID; + _supla_int_t Func; + unsigned char ResultCode; +} TSC_SetChannelFunctionResult; // v. >= 12 + +typedef struct { + _supla_int_t ID; + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CAPTION_MAXSIZE]; // Last variable in struct! +} TCS_SetCaption; // v. >= 12 + +typedef struct { + _supla_int_t ID; + unsigned char ResultCode; + unsigned _supla_int_t + CaptionSize; // including the terminating null byte ('\0') + char Caption[SUPLA_CAPTION_MAXSIZE]; // Last variable in struct! +} TSC_SetCaptionResult; // v. >= 12 + +typedef struct { + unsigned char ResultCode; +} TSC_ClientsReconnectRequestResult; // v. >= 12 + +typedef struct { + // Disabled: 0 + // Ignore: <0 + _supla_int_t IODeviceRegistrationTimeSec; + _supla_int_t ClientRegistrationTimeSec; +} TCS_SetRegistrationEnabled; // v. >= 12 + +typedef struct { + unsigned char ResultCode; +} TSC_SetRegistrationEnabledResult; // v. >= 12 + +typedef struct { + int DeviceID; +} TCS_DeviceReconnectRequest; // v. >= 12 + +typedef struct { + int DeviceID; + unsigned char ResultCode; +} TSC_DeviceReconnectRequestResult; // v. >= 12 + +typedef struct { + // server -> device + + unsigned char ChannelCount; + _supla_int_t Functions[SUPLA_CHANNELMAXCOUNT]; // Last variable in struct! + // Functions[ChannelNumber] +} TSD_ChannelFunctions; // ver. >= 12 + +typedef struct { + unsigned char ChannelNumber; +} TDS_GetChannelIntParamsRequest; + +typedef struct { + unsigned char ChannelNumber; + _supla_int_t Param1; + _supla_int_t Param2; + _supla_int_t Param3; +} TSD_ChannelIntParams; + +#define SUPLA_CHANNEL_CONFIG_MAXSIZE 128 +#define SUPLA_CONFIG_TYPE_DEFAULT 0 + +typedef struct { + unsigned char ChannelNumber; + unsigned char ConfigType; + unsigned _supla_int_t Flags; +} TDS_GetChannelConfigRequest; // v. >= 16 + +typedef struct { + unsigned char ChannelNumber; + _supla_int_t Func; + unsigned char ConfigType; + unsigned short ConfigSize; + char Config[SUPLA_CHANNEL_CONFIG_MAXSIZE]; // Last variable in struct! v. >= + // 16. TSD_DeviceChannelConfig_* +} TSD_ChannelConfig; + +typedef struct { + _supla_int_t TimeMS; +} TSD_ChannelConfig_StaircaseTimer; // v. >= 16 + +typedef struct { + _supla_int_t ClosingTimeMS; + _supla_int_t OpeningTimeMS; +} TSD_ChannelConfig_Rollershutter; // v. >= 16 + +typedef struct { + unsigned _supla_int_t ActiveActions; +} TSD_ChannelConfig_ActionTrigger; // v. >= 16 + +typedef struct { + _supla_int_t ChannelID; + unsigned _supla_int_t DurationMS; + unsigned char On; +} TCS_TimerArmRequest; // v. >= 17 + +// Recommended for bistable buttons +#define SUPLA_ACTION_CAP_TURN_ON (1 << 0) +#define SUPLA_ACTION_CAP_TURN_OFF (1 << 1) +#define SUPLA_ACTION_CAP_TOGGLE_x1 (1 << 2) +#define SUPLA_ACTION_CAP_TOGGLE_x2 (1 << 3) +#define SUPLA_ACTION_CAP_TOGGLE_x3 (1 << 4) +#define SUPLA_ACTION_CAP_TOGGLE_x4 (1 << 5) +#define SUPLA_ACTION_CAP_TOGGLE_x5 (1 << 6) + +// Recommended for monostable buttons +#define SUPLA_ACTION_CAP_HOLD (1 << 10) +#define SUPLA_ACTION_CAP_SHORT_PRESS_x1 (1 << 11) +#define SUPLA_ACTION_CAP_SHORT_PRESS_x2 (1 << 12) +#define SUPLA_ACTION_CAP_SHORT_PRESS_x3 (1 << 13) +#define SUPLA_ACTION_CAP_SHORT_PRESS_x4 (1 << 14) +#define SUPLA_ACTION_CAP_SHORT_PRESS_x5 (1 << 15) + +#define SUPLA_VALVE_FLAG_FLOODING 0x1 +#define SUPLA_VALVE_FLAG_MANUALLY_CLOSED 0x2 + +typedef struct { + union { + unsigned char closed; + unsigned char closed_percent; + }; + + unsigned char flags; +} TValve_Value; + +typedef struct { + unsigned char ChannelNumber; + _supla_int_t ActionTrigger; + unsigned char zero[10]; // Place for future variables +} TDS_ActionTrigger; + +#pragma pack(pop) + +void *PROTO_ICACHE_FLASH sproto_init(void); +void PROTO_ICACHE_FLASH sproto_free(void *spd_ptr); + +#ifndef SPROTO_WITHOUT_OUT_BUFFER +char PROTO_ICACHE_FLASH sproto_out_buffer_append(void *spd_ptr, + TSuplaDataPacket *sdp); +unsigned _supla_int_t sproto_pop_out_data(void *spd_ptr, char *buffer, + unsigned _supla_int_t buffer_size); +#endif /*SPROTO_WITHOUT_OUT_BUFFER*/ +char PROTO_ICACHE_FLASH sproto_out_dataexists(void *spd_ptr); +char PROTO_ICACHE_FLASH sproto_in_buffer_append( + void *spd_ptr, char *data, unsigned _supla_int_t data_size); + +char PROTO_ICACHE_FLASH sproto_pop_in_sdp(void *spd_ptr, TSuplaDataPacket *sdp); +char PROTO_ICACHE_FLASH sproto_in_dataexists(void *spd_ptr); + +unsigned char PROTO_ICACHE_FLASH sproto_get_version(void *spd_ptr); +void PROTO_ICACHE_FLASH sproto_set_version(void *spd_ptr, + unsigned char version); +void PROTO_ICACHE_FLASH sproto_sdp_init(void *spd_ptr, TSuplaDataPacket *sdp); +char PROTO_ICACHE_FLASH sproto_set_data(TSuplaDataPacket *sdp, char *data, + unsigned _supla_int_t data_size, + unsigned _supla_int_t call_type); +TSuplaDataPacket *PROTO_ICACHE_FLASH sproto_sdp_malloc(void *spd_ptr); +void PROTO_ICACHE_FLASH sproto_sdp_free(TSuplaDataPacket *sdp); + +void PROTO_ICACHE_FLASH sproto_log_summary(void *spd_ptr); +void PROTO_ICACHE_FLASH sproto_buffer_dump(void *spd_ptr, unsigned char in); + +#ifdef __cplusplus +} +#endif + +#endif /* supla_proto_H_ */ diff --git a/lib/SuplaDevice/src/supla-common/srpc.c b/lib/SuplaDevice/src/supla-common/srpc.c index 5947996b..a4d11362 100644 --- a/lib/SuplaDevice/src/supla-common/srpc.c +++ b/lib/SuplaDevice/src/supla-common/srpc.c @@ -1,2928 +1,2928 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "srpc.h" - -#include -#include - -#include "lck.h" -#include "log.h" -#include "proto.h" - -#if defined(ESP8266) || defined(ESP32) - -#include -#if !defined(ESP32) -#include -#endif - -#if defined(ARDUINO_ARCH_ESP8266) -#include -#define __EH_DISABLED -#elif defined(ARDUINO_ARCH_ESP32) -#define __EH_DISABLED -#else -#include - -#include "espmissingincludes.h" -#endif - -#ifndef SRPC_BUFFER_SIZE -#define SRPC_BUFFER_SIZE 1024 -#endif /*SRPC_BUFFER_SIZE*/ - -#ifndef SRPC_QUEUE_SIZE -#define SRPC_QUEUE_SIZE 2 -#endif /*SRPC_QUEUE_SIZE*/ - -#ifndef SRPC_QUEUE_MIN_ALLOC_COUNT -#define SRPC_QUEUE_MIN_ALLOC_COUNT 2 -#endif /* SRPC_QUEUE_MIN_ALLOC_COUNT */ - -#elif defined(__AVR__) - -#define SRPC_BUFFER_SIZE 32 -#define SRPC_QUEUE_SIZE 1 -#define SRPC_QUEUE_MIN_ALLOC_COUNT 1 -#define __EH_DISABLED - -#else -#include -#endif - -#ifndef SRPC_BUFFER_SIZE -#define SRPC_BUFFER_SIZE 32768 -#endif /*SRPC_BUFFER_SIZE*/ - -#ifndef SRPC_QUEUE_SIZE -#define SRPC_QUEUE_SIZE 10 -#endif /*SRPC_QUEUE_SIZE*/ - -#ifndef SRPC_QUEUE_MIN_ALLOC_COUNT -#define SRPC_QUEUE_MIN_ALLOC_COUNT 0 -#endif /*SRPC_QUEUE_MIN_ALLOC_COUNT*/ - -typedef struct { - unsigned char item_count; - unsigned char alloc_count; - - TSuplaDataPacket *item[SRPC_QUEUE_SIZE]; -} Tsrpc_Queue; - -typedef struct { - void *proto; - TsrpcParams params; - - TSuplaDataPacket sdp; - -#ifndef SRPC_WITHOUT_IN_QUEUE - Tsrpc_Queue in_queue; -#endif /*SRPC_WITHOUT_IN_QUEUE*/ - -#ifndef SRPC_WITHOUT_OUT_QUEUE - Tsrpc_Queue out_queue; -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ - - void *lck; -} Tsrpc; - -void SRPC_ICACHE_FLASH srpc_params_init(TsrpcParams *params) { - memset(params, 0, sizeof(TsrpcParams)); -} - -void *SRPC_ICACHE_FLASH srpc_init(TsrpcParams *params) { - Tsrpc *srpc = (Tsrpc *)malloc(sizeof(Tsrpc)); - - if (srpc == NULL) return NULL; - - memset(srpc, 0, sizeof(Tsrpc)); - srpc->proto = sproto_init(); - -#ifndef ESP8266 -#ifndef ESP32 -#ifndef __AVR__ - assert(params != 0); - assert(params->data_read != 0); - assert(params->data_write != 0); -#endif -#endif -#endif - - memcpy(&srpc->params, params, sizeof(TsrpcParams)); - - srpc->lck = lck_init(); - - return srpc; -} - -void SRPC_ICACHE_FLASH srpc_queue_free(Tsrpc_Queue *queue) { - _supla_int_t a; - for (a = 0; a < SRPC_QUEUE_SIZE; a++) { - if (queue->item[a] != NULL) { - free(queue->item[a]); - } - } - - queue->item_count = 0; - queue->alloc_count = 0; -} - -void SRPC_ICACHE_FLASH srpc_free(void *_srpc) { - if (_srpc) { - Tsrpc *srpc = (Tsrpc *)_srpc; - - sproto_free(srpc->proto); - -#ifndef SRPC_WITHOUT_IN_QUEUE - srpc_queue_free(&srpc->in_queue); -#endif /*SRPC_WITHOUT_IN_QUEUE*/ - -#ifndef SRPC_WITHOUT_OUT_QUEUE - srpc_queue_free(&srpc->out_queue); -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ - lck_free(srpc->lck); - - free(srpc); - } -} - -char SRPC_ICACHE_FLASH srpc_queue_push(Tsrpc_Queue *queue, - TSuplaDataPacket *sdp) { - if (queue->item_count >= SRPC_QUEUE_SIZE) { - return SUPLA_RESULT_FALSE; - } - - if (queue->item[queue->item_count] == NULL) { - queue->item[queue->item_count] = - (TSuplaDataPacket *)malloc(sizeof(TSuplaDataPacket)); - } - - if (queue->item[queue->item_count] == NULL) { - return SUPLA_RESULT_FALSE; - } else { - queue->alloc_count++; - } - - memcpy(queue->item[queue->item_count], sdp, sizeof(TSuplaDataPacket)); - queue->item_count++; - - return SUPLA_RESULT_TRUE; -} - -char SRPC_ICACHE_FLASH srpc_queue_pop(Tsrpc_Queue *queue, TSuplaDataPacket *sdp, - unsigned _supla_int_t rr_id) { - _supla_int_t a, b; - - for (a = 0; a < queue->item_count; a++) - if (rr_id == 0 || queue->item[a]->rr_id == rr_id) { - memcpy(sdp, queue->item[a], sizeof(TSuplaDataPacket)); - - if (queue->alloc_count > SRPC_QUEUE_MIN_ALLOC_COUNT) { - queue->alloc_count--; - free(queue->item[a]); - queue->item[a] = NULL; - } - - TSuplaDataPacket *item = queue->item[a]; - - for (b = a; b < queue->item_count - 1; b++) { - queue->item[b] = queue->item[b + 1]; - } - - queue->item_count--; - queue->item[queue->item_count] = item; - - return SUPLA_RESULT_TRUE; - } - - return SUPLA_RESULT_FALSE; -} - -char SRPC_ICACHE_FLASH srpc_in_queue_pop(Tsrpc *srpc, TSuplaDataPacket *sdp, - unsigned _supla_int_t rr_id) { -#ifdef SRPC_WITHOUT_IN_QUEUE - return 1; -#else - return srpc_queue_pop(&srpc->in_queue, sdp, rr_id); -#endif /*SRPC_WITHOUT_IN_QUEUE*/ -} - -#ifndef SRPC_WITHOUT_IN_QUEUE -char SRPC_ICACHE_FLASH srpc_in_queue_push(Tsrpc *srpc, TSuplaDataPacket *sdp) { - return srpc_queue_push(&srpc->in_queue, sdp); -} -#endif /*SRPC_WITHOUT_IN_QUEUE*/ - -char SRPC_ICACHE_FLASH srpc_out_queue_push(Tsrpc *srpc, TSuplaDataPacket *sdp) { -#ifdef SRPC_WITHOUT_OUT_QUEUE - unsigned _supla_int_t data_size = sizeof(TSuplaDataPacket); - if (sdp->data_size < SUPLA_MAX_DATA_SIZE) { - data_size -= SUPLA_MAX_DATA_SIZE - sdp->data_size; - } -#ifndef PACKET_INTEGRITY_BUFFER_DISABLED - char *buff = malloc(data_size + SUPLA_TAG_SIZE); - if (buff) { - memcpy(buff, sdp, data_size); - memcpy(&buff[data_size], sproto_tag, SUPLA_TAG_SIZE); - - srpc->params.data_write(buff, data_size + SUPLA_TAG_SIZE, - srpc->params.user_params); - free(buff); - } -#else - srpc->params.data_write((char *)sdp, data_size, srpc->params.user_params); - srpc->params.data_write(sproto_tag, SUPLA_TAG_SIZE, srpc->params.user_params); -#endif /*PACKET_INTEGRITY_BUFFER_DISABLED*/ - return 1; -#else - return srpc_queue_push(&srpc->out_queue, sdp); -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ -} - -#ifndef SRPC_WITHOUT_OUT_QUEUE -char SRPC_ICACHE_FLASH srpc_out_queue_pop(Tsrpc *srpc, TSuplaDataPacket *sdp, - unsigned _supla_int_t rr_id) { - return srpc_queue_pop(&srpc->out_queue, sdp, rr_id); -} -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ - -unsigned char SRPC_ICACHE_FLASH srpc_out_queue_item_count(void *srpc) { -#ifdef SRPC_WITHOUT_OUT_QUEUE - return 0; -#else - return ((Tsrpc *)srpc)->out_queue.item_count; -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ -} - -char SRPC_ICACHE_FLASH srpc_input_dataexists(void *_srpc) { - int result = SUPLA_RESULT_FALSE; - Tsrpc *srpc = (Tsrpc *)_srpc; - lck_lock(srpc->lck); - result = sproto_in_dataexists(srpc->proto); - return lck_unlock_r(srpc->lck, result); -} - -char SRPC_ICACHE_FLASH srpc_output_dataexists(void *_srpc) { - int result = SUPLA_RESULT_FALSE; - Tsrpc *srpc = (Tsrpc *)_srpc; - lck_lock(srpc->lck); - result = sproto_out_dataexists(srpc->proto); - return lck_unlock_r(srpc->lck, result); -} - -char SRPC_ICACHE_FLASH srpc_iterate(void *_srpc) { - Tsrpc *srpc = (Tsrpc *)_srpc; - char data_buffer[SRPC_BUFFER_SIZE]; - char result; - unsigned char version; -#ifndef __EH_DISABLED - unsigned char raise_event = 0; -#endif /*__EH_DISABLED*/ - - // --------- IN --------------- - _supla_int_t data_size = srpc->params.data_read(data_buffer, SRPC_BUFFER_SIZE, - srpc->params.user_params); - - if (data_size == 0) return SUPLA_RESULT_FALSE; - - lck_lock(srpc->lck); - - if (data_size > 0 && - SUPLA_RESULT_TRUE != (result = sproto_in_buffer_append( - srpc->proto, data_buffer, data_size))) { - supla_log(LOG_DEBUG, "sproto_in_buffer_append: %i, datasize: %i", result, - data_size); - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); - } - - if (SUPLA_RESULT_TRUE == - (result = sproto_pop_in_sdp(srpc->proto, &srpc->sdp))) { -#ifndef __EH_DISABLED - raise_event = sproto_in_dataexists(srpc->proto) == 1 ? 1 : 0; -#endif /*__EH_DISABLED*/ - -#ifdef SRPC_WITHOUT_IN_QUEUE - if (srpc->params.on_remote_call_received) { - lck_unlock(srpc->lck); - srpc->params.on_remote_call_received( - srpc, srpc->sdp.rr_id, srpc->sdp.call_type, srpc->params.user_params, - srpc->sdp.version); - lck_lock(srpc->lck); - } -#else - if (SUPLA_RESULT_TRUE == srpc_in_queue_push(srpc, &srpc->sdp)) { - if (srpc->params.on_remote_call_received) { - lck_unlock(srpc->lck); - srpc->params.on_remote_call_received( - srpc, srpc->sdp.rr_id, srpc->sdp.call_type, - srpc->params.user_params, srpc->sdp.version); - lck_lock(srpc->lck); - } - - } else { - supla_log(LOG_DEBUG, "ssrpc_in_queue_push error"); - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); - } -#endif /*SRPC_WITHOUT_IN_QUEUE*/ - - } else if (result != SUPLA_RESULT_FALSE) { - if (result == (char)SUPLA_RESULT_VERSION_ERROR) { - if (srpc->params.on_version_error) { - version = srpc->sdp.version; - lck_unlock(srpc->lck); - - srpc->params.on_version_error(srpc, version, srpc->params.user_params); - return SUPLA_RESULT_FALSE; - } - } else { - supla_log(LOG_DEBUG, "sproto_pop_in_sdp error: %i", result); - } - - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); - } - - // --------- OUT --------------- -#ifndef SRPC_WITHOUT_OUT_QUEUE - if (srpc_out_queue_pop(srpc, &srpc->sdp, 0) == SUPLA_RESULT_TRUE && - SUPLA_RESULT_TRUE != - (result = sproto_out_buffer_append(srpc->proto, &srpc->sdp)) && - result != SUPLA_RESULT_FALSE) { - supla_log(LOG_DEBUG, "sproto_out_buffer_append error: %i", result); - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); - } - - data_size = sproto_pop_out_data(srpc->proto, data_buffer, SRPC_BUFFER_SIZE); - - if (data_size != 0) { - lck_unlock(srpc->lck); - srpc->params.data_write(data_buffer, data_size, srpc->params.user_params); - lck_lock(srpc->lck); - } - -#ifndef __EH_DISABLED - if (srpc->params.eh != 0 && - (sproto_out_dataexists(srpc->proto) == 1 || - srpc_out_queue_item_count(srpc) || raise_event)) { - eh_raise_event(srpc->params.eh); - } -#endif /*__EH_DISABLED*/ - -#else /*SRPC_WITHOUT_OUT_QUEUE*/ -#ifndef __EH_DISABLED - if (srpc->params.eh != 0 && raise_event) { - eh_raise_event(srpc->params.eh); - } -#endif /*__EH_DISABLED*/ -#endif /*SRPC_WITHOUT_OUT_QUEUE*/ - return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); -} - -typedef unsigned _supla_int_t (*_func_srpc_pack_get_caption_size)( - void *pack, _supla_int_t idx); -typedef void *(*_func_srpc_pack_get_item_ptr)(void *pack, _supla_int_t idx); -typedef _supla_int_t (*_func_srpc_pack_get_pack_count)(void *pack); -typedef void (*_func_srpc_pack_set_pack_count)(void *pack, _supla_int_t count, - unsigned char increment); -typedef unsigned _supla_int_t (*_func_srpc_pack_get_item_caption_size)( - void *item); -typedef unsigned _supla_int_t (*_func_srpc_pack_get_caption_size)( - void *pack, _supla_int_t idx); - -void SRPC_ICACHE_FLASH srpc_getpack( - Tsrpc *srpc, TsrpcReceivedData *rd, unsigned _supla_int_t pack_sizeof, - unsigned _supla_int_t item_sizeof, unsigned _supla_int_t pack_max_count, - unsigned _supla_int_t caption_max_size, - _func_srpc_pack_get_pack_count pack_get_count, - _func_srpc_pack_set_pack_count pack_set_count, - _func_srpc_pack_get_item_ptr get_item_ptr, - _func_srpc_pack_get_item_caption_size get_item_caption_size) { - _supla_int_t header_size = pack_sizeof - (item_sizeof * pack_max_count); - _supla_int_t c_header_size = item_sizeof - caption_max_size; - _supla_int_t a, count, size, offset, pack_size; - void *pack = NULL; - - if (srpc->sdp.data_size < header_size || srpc->sdp.data_size > pack_sizeof) { - return; - } - - count = pack_get_count(srpc->sdp.data); - - if (count < 0 || count > pack_max_count) { - return; - } - - pack_size = header_size + (item_sizeof * count); - pack = (TSC_SuplaChannelPack *)malloc(pack_size); - - if (pack == NULL) return; - - memset(pack, 0, pack_size); - memcpy(pack, srpc->sdp.data, header_size); - - offset = header_size; - pack_set_count(pack, 0, 0); - - for (a = 0; a < count; a++) - if (srpc->sdp.data_size - offset >= c_header_size) { - size = get_item_caption_size(&srpc->sdp.data[offset]); - - if (size >= 0 && size <= caption_max_size && - srpc->sdp.data_size - offset >= c_header_size + size) { - memcpy(get_item_ptr(pack, a), &srpc->sdp.data[offset], - c_header_size + size); - offset += c_header_size + size; - pack_set_count(pack, 1, 1); - - } else { - break; - } - } - - if (count == pack_get_count(pack)) { - srpc->sdp.data_size = 0; - // dcs_ping is 1st variable in union - rd->data.dcs_ping = pack; - - } else { - free(pack); - } -} - -void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaChannelPack *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count(void *pack) { - return ((TSC_SuplaChannelPack *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelPack *)pack)->count = count; - } else { - ((TSC_SuplaChannelPack *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelpack_get_item_caption_size(void *item) { - return ((TSC_SuplaChannel *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelpack(Tsrpc *srpc, TsrpcReceivedData *rd) { - srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelPack), sizeof(TSC_SuplaChannel), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - &srpc_channelpack_get_pack_count, - &srpc_channelpack_set_pack_count, &srpc_channelpack_get_item_ptr, - &srpc_channelpack_get_item_caption_size); -} - -void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_b(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaChannelPack_B *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_b(void *pack) { - return ((TSC_SuplaChannelPack_B *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_b( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelPack_B *)pack)->count = count; - } else { - ((TSC_SuplaChannelPack_B *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelpack_get_item_caption_size_b(void *item) { - return ((TSC_SuplaChannel_B *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelpack_b(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack( - srpc, rd, sizeof(TSC_SuplaChannelPack_B), sizeof(TSC_SuplaChannel_B), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - &srpc_channelpack_get_pack_count_b, &srpc_channelpack_set_pack_count_b, - &srpc_channelpack_get_item_ptr_b, - &srpc_channelpack_get_item_caption_size_b); -} - -void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_c(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaChannelPack_C *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_c(void *pack) { - return ((TSC_SuplaChannelPack_C *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_c( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelPack_C *)pack)->count = count; - } else { - ((TSC_SuplaChannelPack_C *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelpack_get_item_caption_size_c(void *item) { - return ((TSC_SuplaChannel_C *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelpack_c(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack( - srpc, rd, sizeof(TSC_SuplaChannelPack_C), sizeof(TSC_SuplaChannel_C), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - &srpc_channelpack_get_pack_count_c, &srpc_channelpack_set_pack_count_c, - &srpc_channelpack_get_item_ptr_c, - &srpc_channelpack_get_item_caption_size_c); -} - -void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_d(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaChannelPack_D *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_d(void *pack) { - return ((TSC_SuplaChannelPack_D *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_d( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelPack_D *)pack)->count = count; - } else { - ((TSC_SuplaChannelPack_D *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelpack_get_item_caption_size_d(void *item) { - return ((TSC_SuplaChannel_D *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelpack_d(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack( - srpc, rd, sizeof(TSC_SuplaChannelPack_D), sizeof(TSC_SuplaChannel_D), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - &srpc_channelpack_get_pack_count_d, &srpc_channelpack_set_pack_count_d, - &srpc_channelpack_get_item_ptr_d, - &srpc_channelpack_get_item_caption_size_d); -} - -void *SRPC_ICACHE_FLASH srpc_channelgroup_pack_get_item_ptr(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaChannelGroupPack *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_channelgroup_pack_get_pack_count(void *pack) { - return ((TSC_SuplaChannelGroupPack *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelgroup_pack_set_pack_count( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelGroupPack *)pack)->count = count; - } else { - ((TSC_SuplaChannelGroupPack *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelgroup_pack_get_item_caption_size(void *item) { - return ((TSC_SuplaChannelGroup *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelgroup_pack(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelGroupPack), - sizeof(TSC_SuplaChannelGroup), SUPLA_CHANNELGROUP_PACK_MAXCOUNT, - SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, - &srpc_channelgroup_pack_get_pack_count, - &srpc_channelgroup_pack_set_pack_count, - &srpc_channelgroup_pack_get_item_ptr, - &srpc_channelgroup_pack_get_item_caption_size); -} - -void *SRPC_ICACHE_FLASH -srpc_channelgroup_pack_b_get_item_ptr(void *pack, _supla_int_t idx) { - return &((TSC_SuplaChannelGroupPack_B *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_channelgroup_pack_b_get_pack_count(void *pack) { - return ((TSC_SuplaChannelGroupPack_B *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_channelgroup_pack_b_set_pack_count( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaChannelGroupPack_B *)pack)->count = count; - } else { - ((TSC_SuplaChannelGroupPack_B *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_channelgroup_pack_b_get_item_caption_size(void *item) { - return ((TSC_SuplaChannelGroup_B *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getchannelgroup_pack_b(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelGroupPack_B), - sizeof(TSC_SuplaChannelGroup_B), - SUPLA_CHANNELGROUP_PACK_MAXCOUNT, - SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, - &srpc_channelgroup_pack_b_get_pack_count, - &srpc_channelgroup_pack_b_set_pack_count, - &srpc_channelgroup_pack_b_get_item_ptr, - &srpc_channelgroup_pack_b_get_item_caption_size); -} - -void *SRPC_ICACHE_FLASH srpc_locationpack_get_item_ptr(void *pack, - _supla_int_t idx) { - return &((TSC_SuplaLocationPack *)pack)->items[idx]; // NOLINT -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_locationpack_get_pack_count(void *pack) { - return ((TSC_SuplaLocationPack *)pack)->count; -} - -void SRPC_ICACHE_FLASH srpc_locationpack_set_pack_count( - void *pack, _supla_int_t count, unsigned char increment) { - if (increment == 0) { - ((TSC_SuplaLocationPack *)pack)->count = count; - } else { - ((TSC_SuplaLocationPack *)pack)->count += count; - } -} - -unsigned _supla_int_t SRPC_ICACHE_FLASH -srpc_locationpack_get_item_caption_size(void *item) { - return ((TSC_SuplaLocation *)item)->CaptionSize; -} - -void SRPC_ICACHE_FLASH srpc_getlocationpack(Tsrpc *srpc, - TsrpcReceivedData *rd) { - srpc_getpack( - srpc, rd, sizeof(TSC_SuplaLocationPack), sizeof(TSC_SuplaLocation), - SUPLA_LOCATIONPACK_MAXCOUNT, SUPLA_LOCATION_CAPTION_MAXSIZE, - &srpc_locationpack_get_pack_count, &srpc_locationpack_set_pack_count, - &srpc_locationpack_get_item_ptr, - &srpc_locationpack_get_item_caption_size); -} - -char SRPC_ICACHE_FLASH srpc_getdata(void *_srpc, TsrpcReceivedData *rd, - unsigned _supla_int_t rr_id) { - Tsrpc *srpc = (Tsrpc *)_srpc; - char call_with_no_data = 0; - rd->call_type = 0; - - lck_lock(srpc->lck); - - if (SUPLA_RESULT_TRUE == srpc_in_queue_pop(srpc, &srpc->sdp, rr_id)) { - rd->call_type = srpc->sdp.call_type; - rd->rr_id = srpc->sdp.rr_id; - - // first one - rd->data.dcs_ping = NULL; - - switch (srpc->sdp.call_type) { - case SUPLA_DCS_CALL_GETVERSION: - case SUPLA_CS_CALL_GET_NEXT: - case SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED: - call_with_no_data = 1; - break; - - case SUPLA_SDC_CALL_GETVERSION_RESULT: - - if (srpc->sdp.data_size == sizeof(TSDC_SuplaGetVersionResult)) - rd->data.sdc_getversion_result = (TSDC_SuplaGetVersionResult *)malloc( - sizeof(TSDC_SuplaGetVersionResult)); - - break; - - case SUPLA_SDC_CALL_VERSIONERROR: - - if (srpc->sdp.data_size == sizeof(TSDC_SuplaVersionError)) - rd->data.sdc_version_error = - (TSDC_SuplaVersionError *)malloc(sizeof(TSDC_SuplaVersionError)); - - break; - - case SUPLA_DCS_CALL_PING_SERVER: - - if (srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer) || - srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer_COMPAT)) { - rd->data.dcs_ping = - (TDCS_SuplaPingServer *)malloc(sizeof(TDCS_SuplaPingServer)); - -#ifndef __AVR__ - if (srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer_COMPAT)) { - TDCS_SuplaPingServer_COMPAT *compat = - (TDCS_SuplaPingServer_COMPAT *)srpc->sdp.data; - - rd->data.dcs_ping->now.tv_sec = compat->now.tv_sec; - rd->data.dcs_ping->now.tv_usec = compat->now.tv_usec; - call_with_no_data = 1; - } -#endif - } - break; - - case SUPLA_SDC_CALL_PING_SERVER_RESULT: - - if (srpc->sdp.data_size == sizeof(TSDC_SuplaPingServerResult)) - rd->data.sdc_ping_result = (TSDC_SuplaPingServerResult *)malloc( - sizeof(TSDC_SuplaPingServerResult)); - - break; - - case SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT: - - if (srpc->sdp.data_size == sizeof(TDCS_SuplaSetActivityTimeout)) - rd->data.dcs_set_activity_timeout = - (TDCS_SuplaSetActivityTimeout *)malloc( - sizeof(TDCS_SuplaSetActivityTimeout)); - - break; - - case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: - - if (srpc->sdp.data_size == sizeof(TSDC_SuplaSetActivityTimeoutResult)) - rd->data.sdc_set_activity_timeout_result = - (TSDC_SuplaSetActivityTimeoutResult *)malloc( - sizeof(TSDC_SuplaSetActivityTimeoutResult)); - - break; - - case SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT: - - if (srpc->sdp.data_size == sizeof(TSDC_RegistrationEnabled)) - rd->data.sdc_reg_enabled = (TSDC_RegistrationEnabled *)malloc( - sizeof(TSDC_RegistrationEnabled)); - - break; - case SUPLA_DCS_CALL_GET_USER_LOCALTIME: - call_with_no_data = 1; - break; - case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: - if (srpc->sdp.data_size <= sizeof(TSDC_UserLocalTimeResult) && - srpc->sdp.data_size >= - (sizeof(TSDC_UserLocalTimeResult) - SUPLA_TIMEZONE_MAXSIZE)) { - rd->data.sdc_user_localtime_result = - (TSDC_UserLocalTimeResult *)malloc( - sizeof(TSDC_UserLocalTimeResult)); - } - - break; - - case SUPLA_CSD_CALL_GET_CHANNEL_STATE: - if (srpc->sdp.data_size == sizeof(TCSD_ChannelStateRequest)) - rd->data.csd_channel_state_request = - (TCSD_ChannelStateRequest *)malloc( - sizeof(TCSD_ChannelStateRequest)); - break; - case SUPLA_DSC_CALL_CHANNEL_STATE_RESULT: - if (srpc->sdp.data_size == sizeof(TDSC_ChannelState)) - rd->data.dsc_channel_state = - (TDSC_ChannelState *)malloc(sizeof(TDSC_ChannelState)); - break; - -#ifndef SRPC_EXCLUDE_DEVICE - case SUPLA_DS_CALL_REGISTER_DEVICE: - - if (srpc->sdp.data_size >= - (sizeof(TDS_SuplaRegisterDevice) - - (sizeof(TDS_SuplaDeviceChannel) * SUPLA_CHANNELMAXCOUNT)) && - srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice)) { - rd->data.ds_register_device = (TDS_SuplaRegisterDevice *)malloc( - sizeof(TDS_SuplaRegisterDevice)); - } - - break; - - case SUPLA_DS_CALL_REGISTER_DEVICE_B: // ver. >= 2 - - if (srpc->sdp.data_size >= - (sizeof(TDS_SuplaRegisterDevice_B) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && - srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_B)) { - rd->data.ds_register_device_b = (TDS_SuplaRegisterDevice_B *)malloc( - sizeof(TDS_SuplaRegisterDevice_B)); - } - - break; - - case SUPLA_DS_CALL_REGISTER_DEVICE_C: // ver. >= 6 - - if (srpc->sdp.data_size >= - (sizeof(TDS_SuplaRegisterDevice_C) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && - srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_C)) { - rd->data.ds_register_device_c = (TDS_SuplaRegisterDevice_C *)malloc( - sizeof(TDS_SuplaRegisterDevice_C)); - } - - break; - - case SUPLA_DS_CALL_REGISTER_DEVICE_D: // ver. >= 7 - - if (srpc->sdp.data_size >= - (sizeof(TDS_SuplaRegisterDevice_D) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && - srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_D)) { - rd->data.ds_register_device_d = (TDS_SuplaRegisterDevice_D *)malloc( - sizeof(TDS_SuplaRegisterDevice_D)); - } - - break; - - case SUPLA_DS_CALL_REGISTER_DEVICE_E: // ver. >= 10 - - if (srpc->sdp.data_size >= - (sizeof(TDS_SuplaRegisterDevice_E) - - (sizeof(TDS_SuplaDeviceChannel_C) * SUPLA_CHANNELMAXCOUNT)) && - srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_E)) { - rd->data.ds_register_device_e = (TDS_SuplaRegisterDevice_E *)malloc( - sizeof(TDS_SuplaRegisterDevice_E)); - } - - break; - - case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: - - if (srpc->sdp.data_size == sizeof(TSD_SuplaRegisterDeviceResult)) - rd->data.sd_register_device_result = - (TSD_SuplaRegisterDeviceResult *)malloc( - sizeof(TSD_SuplaRegisterDeviceResult)); - break; - - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED: - - if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue)) - rd->data.ds_device_channel_value = - (TDS_SuplaDeviceChannelValue *)malloc( - sizeof(TDS_SuplaDeviceChannelValue)); - - break; - - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B: - - if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue_B)) - rd->data.ds_device_channel_value_b = - (TDS_SuplaDeviceChannelValue_B *)malloc( - sizeof(TDS_SuplaDeviceChannelValue_B)); - - break; - - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C: - - if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue_C)) - rd->data.ds_device_channel_value_c = - (TDS_SuplaDeviceChannelValue_C *)malloc( - sizeof(TDS_SuplaDeviceChannelValue_C)); - - break; - - case SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED: - - if (srpc->sdp.data_size <= - sizeof(TDS_SuplaDeviceChannelExtendedValue) && - srpc->sdp.data_size >= - (sizeof(TDS_SuplaDeviceChannelExtendedValue) - - SUPLA_CHANNELEXTENDEDVALUE_SIZE)) - rd->data.ds_device_channel_extendedvalue = - (TDS_SuplaDeviceChannelExtendedValue *)malloc( - sizeof(TDS_SuplaDeviceChannelExtendedValue)); - - break; - - case SUPLA_SD_CALL_CHANNEL_SET_VALUE: - - if (srpc->sdp.data_size == sizeof(TSD_SuplaChannelNewValue)) - rd->data.sd_channel_new_value = (TSD_SuplaChannelNewValue *)malloc( - sizeof(TSD_SuplaChannelNewValue)); - - break; - - case SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE: - - if (srpc->sdp.data_size == sizeof(TSD_SuplaChannelGroupNewValue)) - rd->data.sd_channelgroup_new_value = - (TSD_SuplaChannelGroupNewValue *)malloc( - sizeof(TSD_SuplaChannelGroupNewValue)); - - break; - - case SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT: - - if (srpc->sdp.data_size == sizeof(TDS_SuplaChannelNewValueResult)) - rd->data.ds_channel_new_value_result = - (TDS_SuplaChannelNewValueResult *)malloc( - sizeof(TDS_SuplaChannelNewValueResult)); - - break; - - case SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL: - - if (srpc->sdp.data_size == sizeof(TDS_FirmwareUpdateParams)) - rd->data.ds_firmware_update_params = - (TDS_FirmwareUpdateParams *)malloc( - sizeof(TDS_FirmwareUpdateParams)); - - break; - - case SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT: - - if (srpc->sdp.data_size == sizeof(TSD_FirmwareUpdate_UrlResult) || - srpc->sdp.data_size == sizeof(char)) { - rd->data.sc_firmware_update_url_result = - (TSD_FirmwareUpdate_UrlResult *)malloc( - sizeof(TSD_FirmwareUpdate_UrlResult)); - - if (srpc->sdp.data_size == sizeof(char) && - rd->data.sc_firmware_update_url_result != NULL) - memset(rd->data.sc_firmware_update_url_result, 0, - sizeof(TSD_FirmwareUpdate_UrlResult)); - } - break; - case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: - if (srpc->sdp.data_size <= sizeof(TSD_DeviceCalCfgRequest) && - srpc->sdp.data_size >= - (sizeof(TSD_DeviceCalCfgRequest) - SUPLA_CALCFG_DATA_MAXSIZE)) { - rd->data.sd_device_calcfg_request = (TSD_DeviceCalCfgRequest *)malloc( - sizeof(TSD_DeviceCalCfgRequest)); - } - break; - case SUPLA_DS_CALL_DEVICE_CALCFG_RESULT: - if (srpc->sdp.data_size <= sizeof(TDS_DeviceCalCfgResult) && - srpc->sdp.data_size >= - (sizeof(TDS_DeviceCalCfgResult) - SUPLA_CALCFG_DATA_MAXSIZE)) { - rd->data.ds_device_calcfg_result = - (TDS_DeviceCalCfgResult *)malloc(sizeof(TDS_DeviceCalCfgResult)); - } - break; - case SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS: - call_with_no_data = 1; - break; - case SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT: - if (srpc->sdp.data_size <= sizeof(TSD_ChannelFunctions) && - srpc->sdp.data_size >= - (sizeof(TSD_ChannelFunctions) - - sizeof(_supla_int_t) * SUPLA_CHANNELMAXCOUNT)) { - rd->data.sd_channel_functions = - (TSD_ChannelFunctions *)malloc(sizeof(TSD_ChannelFunctions)); - } - break; - case SUPLA_DS_CALL_GET_CHANNEL_CONFIG: - if (srpc->sdp.data_size == sizeof(TDS_GetChannelConfigRequest)) { - rd->data.ds_get_channel_config_request = - (TDS_GetChannelConfigRequest *)malloc( - sizeof(TDS_GetChannelConfigRequest)); - } - break; - case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: - if (srpc->sdp.data_size <= sizeof(TSD_ChannelConfig) && - srpc->sdp.data_size >= - (sizeof(TSD_ChannelConfig) - SUPLA_CHANNEL_CONFIG_MAXSIZE)) { - rd->data.sd_channel_config = - (TSD_ChannelConfig *)malloc(sizeof(TSD_ChannelConfig)); - } - break; - case SUPLA_DS_CALL_ACTIONTRIGGER: - if (srpc->sdp.data_size == sizeof(TDS_ActionTrigger)) { - rd->data.ds_action_trigger = - (TDS_ActionTrigger *)malloc(sizeof(TDS_ActionTrigger)); - } - break; -#endif /*#ifndef SRPC_EXCLUDE_DEVICE*/ - -#ifndef SRPC_EXCLUDE_CLIENT - case SUPLA_CS_CALL_REGISTER_CLIENT: - - if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient)) - rd->data.cs_register_client = (TCS_SuplaRegisterClient *)malloc( - sizeof(TCS_SuplaRegisterClient)); - - break; - - case SUPLA_CS_CALL_REGISTER_CLIENT_B: // ver. >= 6 - - if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_B)) - rd->data.cs_register_client_b = (TCS_SuplaRegisterClient_B *)malloc( - sizeof(TCS_SuplaRegisterClient_B)); - - break; - - case SUPLA_CS_CALL_REGISTER_CLIENT_C: // ver. >= 7 - - if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_C)) - rd->data.cs_register_client_c = (TCS_SuplaRegisterClient_C *)malloc( - sizeof(TCS_SuplaRegisterClient_C)); - - break; - - case SUPLA_CS_CALL_REGISTER_CLIENT_D: // ver. >= 12 - - if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_D)) - rd->data.cs_register_client_d = (TCS_SuplaRegisterClient_D *)malloc( - sizeof(TCS_SuplaRegisterClient_D)); - - break; - - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT: - - if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult)) - rd->data.sc_register_client_result = - (TSC_SuplaRegisterClientResult *)malloc( - sizeof(TSC_SuplaRegisterClientResult)); - - break; - - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B: - - if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult_B)) - rd->data.sc_register_client_result_b = - (TSC_SuplaRegisterClientResult_B *)malloc( - sizeof(TSC_SuplaRegisterClientResult_B)); - - break; - - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C: - - if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult_C)) - rd->data.sc_register_client_result_c = - (TSC_SuplaRegisterClientResult_C *)malloc( - sizeof(TSC_SuplaRegisterClientResult_C)); - - break; - - case SUPLA_SC_CALL_LOCATION_UPDATE: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaLocation) - SUPLA_LOCATION_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaLocation)) { - rd->data.sc_location = - (TSC_SuplaLocation *)malloc(sizeof(TSC_SuplaLocation)); - } - - break; - - case SUPLA_SC_CALL_LOCATIONPACK_UPDATE: - srpc_getlocationpack(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNEL_UPDATE: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannel) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaChannel)) { - rd->data.sc_channel = - (TSC_SuplaChannel *)malloc(sizeof(TSC_SuplaChannel)); - } - - break; - - case SUPLA_SC_CALL_CHANNEL_UPDATE_B: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannel_B) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_B)) { - rd->data.sc_channel_b = - (TSC_SuplaChannel_B *)malloc(sizeof(TSC_SuplaChannel_B)); - } - - break; - - case SUPLA_SC_CALL_CHANNEL_UPDATE_C: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannel_C) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_C)) { - rd->data.sc_channel_c = - (TSC_SuplaChannel_C *)malloc(sizeof(TSC_SuplaChannel_C)); - } - - break; - - case SUPLA_SC_CALL_CHANNEL_UPDATE_D: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannel_D) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_D)) { - rd->data.sc_channel_d = - (TSC_SuplaChannel_D *)malloc(sizeof(TSC_SuplaChannel_D)); - } - - break; - - case SUPLA_SC_CALL_CHANNELPACK_UPDATE: - srpc_getchannelpack(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_B: - srpc_getchannelpack_b(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_C: - srpc_getchannelpack_c(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_D: - srpc_getchannelpack_d(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE: - - if (srpc->sdp.data_size == sizeof(TSC_SuplaChannelValue)) - rd->data.sc_channel_value = - (TSC_SuplaChannelValue *)malloc(sizeof(TSC_SuplaChannelValue)); - - break; - - case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B: - - if (srpc->sdp.data_size == sizeof(TSC_SuplaChannelValue_B)) - rd->data.sc_channel_value_b = (TSC_SuplaChannelValue_B *)malloc( - sizeof(TSC_SuplaChannelValue_B)); - - break; - - case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE: - srpc_getchannelgroup_pack(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B: - srpc_getchannelgroup_pack_b(srpc, rd); - break; - - case SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE: - if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelGroupRelationPack) && - srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannelGroupRelationPack) - - (sizeof(TSC_SuplaChannelGroupRelation) * - SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT))) { - rd->data.sc_channelgroup_relation_pack = - (TSC_SuplaChannelGroupRelationPack *)malloc( - sizeof(TSC_SuplaChannelGroupRelationPack)); - } - break; - - case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE: - if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelValuePack) && - srpc->sdp.data_size >= (sizeof(TSC_SuplaChannelValuePack) - - (sizeof(TSC_SuplaChannelValue) * - SUPLA_CHANNELVALUE_PACK_MAXCOUNT))) { - rd->data.sc_channelvalue_pack = (TSC_SuplaChannelValuePack *)malloc( - sizeof(TSC_SuplaChannelValuePack)); - } - break; - - case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B: - if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelValuePack_B) && - srpc->sdp.data_size >= (sizeof(TSC_SuplaChannelValuePack_B) - - (sizeof(TSC_SuplaChannelValue_B) * - SUPLA_CHANNELVALUE_PACK_MAXCOUNT))) { - rd->data.sc_channelvalue_pack_b = - (TSC_SuplaChannelValuePack_B *)malloc( - sizeof(TSC_SuplaChannelValuePack_B)); - } - break; - - case SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE: - if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelExtendedValuePack) && - srpc->sdp.data_size >= - (sizeof(TSC_SuplaChannelExtendedValuePack) - - SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE)) { - rd->data.sc_channelextendedvalue_pack = - (TSC_SuplaChannelExtendedValuePack *)malloc( - sizeof(TSC_SuplaChannelExtendedValuePack)); - } - break; - - case SUPLA_CS_CALL_CHANNEL_SET_VALUE: - - if (srpc->sdp.data_size == sizeof(TCS_SuplaChannelNewValue)) - rd->data.cs_channel_new_value = (TCS_SuplaChannelNewValue *)malloc( - sizeof(TCS_SuplaChannelNewValue)); - - break; - - case SUPLA_CS_CALL_SET_VALUE: - - if (srpc->sdp.data_size == sizeof(TCS_SuplaNewValue)) - rd->data.cs_new_value = - (TCS_SuplaNewValue *)malloc(sizeof(TCS_SuplaNewValue)); - - break; - - case SUPLA_CS_CALL_CHANNEL_SET_VALUE_B: - - if (srpc->sdp.data_size == sizeof(TCS_SuplaChannelNewValue_B)) - rd->data.cs_channel_new_value_b = - (TCS_SuplaChannelNewValue_B *)malloc( - sizeof(TCS_SuplaChannelNewValue_B)); - - break; - - case SUPLA_SC_CALL_EVENT: - - if (srpc->sdp.data_size >= - (sizeof(TSC_SuplaEvent) - SUPLA_SENDER_NAME_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SuplaEvent)) { - rd->data.sc_event = (TSC_SuplaEvent *)malloc(sizeof(TSC_SuplaEvent)); - } - - break; - - case SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST: - call_with_no_data = 1; - break; - - case SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT: - if (srpc->sdp.data_size >= (sizeof(TSC_OAuthTokenRequestResult) - - SUPLA_OAUTH_TOKEN_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_OAuthTokenRequestResult)) { - rd->data.sc_oauth_tokenrequest_result = - (TSC_OAuthTokenRequestResult *)malloc( - sizeof(TSC_OAuthTokenRequestResult)); - } - break; - case SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST: - if (srpc->sdp.data_size == sizeof(TCS_SuperUserAuthorizationRequest)) - rd->data.cs_superuser_authorization_request = - (TCS_SuperUserAuthorizationRequest *)malloc( - sizeof(TCS_SuperUserAuthorizationRequest)); - break; - case SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT: - call_with_no_data = 1; - break; - case SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT: - if (srpc->sdp.data_size == sizeof(TSC_SuperUserAuthorizationResult)) - rd->data.sc_superuser_authorization_result = - (TSC_SuperUserAuthorizationResult *)malloc( - sizeof(TSC_SuperUserAuthorizationResult)); - break; - case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST: - if (srpc->sdp.data_size <= sizeof(TCS_DeviceCalCfgRequest) && - srpc->sdp.data_size >= - (sizeof(TCS_DeviceCalCfgRequest) - SUPLA_CALCFG_DATA_MAXSIZE)) { - rd->data.cs_device_calcfg_request = (TCS_DeviceCalCfgRequest *)malloc( - sizeof(TCS_DeviceCalCfgRequest)); - } - break; - case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B: - if (srpc->sdp.data_size <= sizeof(TCS_DeviceCalCfgRequest_B) && - srpc->sdp.data_size >= (sizeof(TCS_DeviceCalCfgRequest_B) - - SUPLA_CALCFG_DATA_MAXSIZE)) { - rd->data.cs_device_calcfg_request_b = - (TCS_DeviceCalCfgRequest_B *)malloc( - sizeof(TCS_DeviceCalCfgRequest_B)); - } - break; - case SUPLA_SC_CALL_DEVICE_CALCFG_RESULT: - if (srpc->sdp.data_size <= sizeof(TSC_DeviceCalCfgResult) && - srpc->sdp.data_size >= - (sizeof(TSC_DeviceCalCfgResult) - SUPLA_CALCFG_DATA_MAXSIZE)) { - rd->data.sc_device_calcfg_result = - (TSC_DeviceCalCfgResult *)malloc(sizeof(TSC_DeviceCalCfgResult)); - } - break; - - case SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG: - if (srpc->sdp.data_size == sizeof(TCS_ChannelBasicCfgRequest)) - rd->data.cs_channel_basic_cfg_request = - (TCS_ChannelBasicCfgRequest *)malloc( - sizeof(TCS_ChannelBasicCfgRequest)); - break; - case SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT: - if (srpc->sdp.data_size >= - (sizeof(TSC_ChannelBasicCfg) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_ChannelBasicCfg)) - rd->data.sc_channel_basic_cfg = - (TSC_ChannelBasicCfg *)malloc(sizeof(TSC_ChannelBasicCfg)); - break; - - case SUPLA_CS_CALL_SET_CHANNEL_FUNCTION: - if (srpc->sdp.data_size == sizeof(TCS_SetChannelFunction)) - rd->data.cs_set_channel_function = - (TCS_SetChannelFunction *)malloc(sizeof(TCS_SetChannelFunction)); - break; - - case SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT: - if (srpc->sdp.data_size == sizeof(TSC_SetChannelFunctionResult)) - rd->data.sc_set_channel_function_result = - (TSC_SetChannelFunctionResult *)malloc( - sizeof(TSC_SetChannelFunctionResult)); - break; - - case SUPLA_CS_CALL_SET_CHANNEL_CAPTION: - case SUPLA_CS_CALL_SET_LOCATION_CAPTION: - if (srpc->sdp.data_size >= - (sizeof(TCS_SetCaption) - SUPLA_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TCS_SetCaption)) - rd->data.cs_set_caption = - (TCS_SetCaption *)malloc(sizeof(TCS_SetCaption)); - break; - - case SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT: - case SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT: - if (srpc->sdp.data_size >= - (sizeof(TSC_SetCaptionResult) - SUPLA_CAPTION_MAXSIZE) && - srpc->sdp.data_size <= sizeof(TSC_SetCaptionResult)) - rd->data.sc_set_caption_result = - (TSC_SetCaptionResult *)malloc(sizeof(TSC_SetCaptionResult)); - break; - - case SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST: - call_with_no_data = 1; - break; - - case SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT: - if (srpc->sdp.data_size == sizeof(TSC_ClientsReconnectRequestResult)) - rd->data.sc_clients_reconnect_result = - (TSC_ClientsReconnectRequestResult *)malloc( - sizeof(TSC_ClientsReconnectRequestResult)); - break; - - case SUPLA_CS_CALL_SET_REGISTRATION_ENABLED: - if (srpc->sdp.data_size == sizeof(TCS_SetRegistrationEnabled)) - rd->data.cs_set_registration_enabled = - (TCS_SetRegistrationEnabled *)malloc( - sizeof(TCS_SetRegistrationEnabled)); - break; - - case SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT: - if (srpc->sdp.data_size == sizeof(TSC_SetRegistrationEnabledResult)) - rd->data.sc_set_registration_enabled_result = - (TSC_SetRegistrationEnabledResult *)malloc( - sizeof(TSC_SetRegistrationEnabledResult)); - break; - - case SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST: - if (srpc->sdp.data_size == sizeof(TCS_DeviceReconnectRequest)) - rd->data.cs_device_reconnect_request = - (TCS_DeviceReconnectRequest *)malloc( - sizeof(TCS_DeviceReconnectRequest)); - break; - case SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT: - if (srpc->sdp.data_size == sizeof(TSC_DeviceReconnectRequestResult)) - rd->data.sc_device_reconnect_request_result = - (TSC_DeviceReconnectRequestResult *)malloc( - sizeof(TSC_DeviceReconnectRequestResult)); - break; - - case SUPLA_CS_CALL_TIMER_ARM: - if (srpc->sdp.data_size == sizeof(TCS_TimerArmRequest)) - rd->data.cs_timer_arm_request = - (TCS_TimerArmRequest *)malloc(sizeof(TCS_TimerArmRequest)); - break; - -#endif /*#ifndef SRPC_EXCLUDE_CLIENT*/ - } - - if (call_with_no_data == 1) { - return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); - } - - if (rd->data.dcs_ping != NULL) { - if (srpc->sdp.data_size > 0) { - memcpy(rd->data.dcs_ping, srpc->sdp.data, srpc->sdp.data_size); - } - - return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); - } - - return lck_unlock_r(srpc->lck, SUPLA_RESULT_DATA_ERROR); - } - - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); -} - -void SRPC_ICACHE_FLASH srpc_rd_free(TsrpcReceivedData *rd) { - if (rd->call_type > 0) { - // first one - - if (rd->data.dcs_ping != NULL) free(rd->data.dcs_ping); - - rd->call_type = 0; - } -} - -unsigned char SRPC_ICACHE_FLASH -srpc_call_min_version_required(void *_srpc, unsigned _supla_int_t call_type) { - switch (call_type) { - case SUPLA_DCS_CALL_GETVERSION: - case SUPLA_SDC_CALL_GETVERSION_RESULT: - case SUPLA_SDC_CALL_VERSIONERROR: - case SUPLA_DCS_CALL_PING_SERVER: - case SUPLA_SDC_CALL_PING_SERVER_RESULT: - case SUPLA_DS_CALL_REGISTER_DEVICE: - case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: - case SUPLA_CS_CALL_REGISTER_CLIENT: - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT: - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED: - case SUPLA_SD_CALL_CHANNEL_SET_VALUE: - case SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT: - case SUPLA_SC_CALL_LOCATION_UPDATE: - case SUPLA_SC_CALL_LOCATIONPACK_UPDATE: - case SUPLA_SC_CALL_CHANNEL_UPDATE: - case SUPLA_SC_CALL_CHANNELPACK_UPDATE: - case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE: - case SUPLA_CS_CALL_GET_NEXT: - case SUPLA_SC_CALL_EVENT: - case SUPLA_CS_CALL_CHANNEL_SET_VALUE: - return 1; - - case SUPLA_DS_CALL_REGISTER_DEVICE_B: - case SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT: - case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: - return 2; - - case SUPLA_CS_CALL_CHANNEL_SET_VALUE_B: - return 3; - - case SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL: - case SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT: - return 5; - - case SUPLA_DS_CALL_REGISTER_DEVICE_C: - case SUPLA_CS_CALL_REGISTER_CLIENT_B: - return 6; - - case SUPLA_CS_CALL_REGISTER_CLIENT_C: - case SUPLA_DS_CALL_REGISTER_DEVICE_D: - case SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED: - case SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT: - return 7; - - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_B: - case SUPLA_SC_CALL_CHANNEL_UPDATE_B: - return 8; - - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B: - case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE: - case SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE: - case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE: - case SUPLA_CS_CALL_SET_VALUE: - return 9; - - case SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED: - case SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE: - case SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST: - case SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT: - case SUPLA_DS_CALL_REGISTER_DEVICE_E: - case SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST: - case SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT: - case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST: - case SUPLA_SC_CALL_DEVICE_CALCFG_RESULT: - case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: - case SUPLA_DS_CALL_DEVICE_CALCFG_RESULT: - case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B: - case SUPLA_SC_CALL_CHANNEL_UPDATE_C: - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_C: - return 10; - case SUPLA_DCS_CALL_GET_USER_LOCALTIME: - case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: - case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B: - return 11; - case SUPLA_CS_CALL_REGISTER_CLIENT_D: - case SUPLA_CSD_CALL_GET_CHANNEL_STATE: - case SUPLA_DSC_CALL_CHANNEL_STATE_RESULT: - case SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG: - case SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT: - case SUPLA_CS_CALL_SET_CHANNEL_FUNCTION: - case SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT: - case SUPLA_CS_CALL_SET_CHANNEL_CAPTION: - case SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT: - case SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST: - case SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT: - case SUPLA_CS_CALL_SET_REGISTRATION_ENABLED: - case SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT: - case SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST: - case SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT: - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B: - case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C: - case SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS: - case SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT: - case SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT: - return 12; - case SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE: - return 13; - case SUPLA_CS_CALL_SET_LOCATION_CAPTION: - case SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT: - return 14; - case SUPLA_SC_CALL_CHANNEL_UPDATE_D: - case SUPLA_SC_CALL_CHANNELPACK_UPDATE_D: - case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B: - case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B: - return 15; - case SUPLA_DS_CALL_GET_CHANNEL_CONFIG: - case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: - case SUPLA_DS_CALL_ACTIONTRIGGER: - return 16; - case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C: - case SUPLA_CS_CALL_TIMER_ARM: - return 17; - } - - return 255; -} - -unsigned char SRPC_ICACHE_FLASH -srpc_call_allowed(void *_srpc, unsigned _supla_int_t call_type) { - unsigned char min_ver = srpc_call_min_version_required(_srpc, call_type); - - if (min_ver == 0 || srpc_get_proto_version(_srpc) >= min_ver) { - return 1; - } - - return 0; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_async__call(void *_srpc, - unsigned _supla_int_t call_type, - char *data, - unsigned _supla_int_t data_size, - unsigned char *version) { - Tsrpc *srpc = (Tsrpc *)_srpc; - - if (!srpc_call_allowed(_srpc, call_type)) { - if (srpc->params.on_min_version_required != NULL) { - srpc->params.on_min_version_required( - _srpc, call_type, srpc_call_min_version_required(_srpc, call_type), - srpc->params.user_params); - } - - return SUPLA_RESULT_FALSE; - } - - if (srpc->params.before_async_call != NULL) { - srpc->params.before_async_call(_srpc, call_type, srpc->params.user_params); - } - - lck_lock(srpc->lck); - - sproto_sdp_init(srpc->proto, &srpc->sdp); - - if (version != NULL) srpc->sdp.version = *version; - - if (SUPLA_RESULT_TRUE == - sproto_set_data(&srpc->sdp, data, data_size, call_type) && - srpc_out_queue_push(srpc, &srpc->sdp)) { -#ifndef __EH_DISABLED - if (srpc->params.eh != 0) { - eh_raise_event(srpc->params.eh); - } -#endif - - return lck_unlock_r(srpc->lck, srpc->sdp.rr_id); - } - - return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_async_call(void *_srpc, unsigned _supla_int_t call_type, char *data, - unsigned _supla_int_t data_size) { - return srpc_async__call(_srpc, call_type, data, data_size, NULL); -} - -unsigned char SRPC_ICACHE_FLASH srpc_get_proto_version(void *_srpc) { - unsigned char version; - - Tsrpc *srpc = (Tsrpc *)_srpc; - lck_lock(srpc->lck); - version = sproto_get_version(srpc->proto); - lck_unlock(srpc->lck); - - return version; -} - -void SRPC_ICACHE_FLASH srpc_set_proto_version(void *_srpc, - unsigned char version) { - Tsrpc *srpc = (Tsrpc *)_srpc; - - lck_lock(srpc->lck); - sproto_set_version(srpc->proto, version); - lck_unlock(srpc->lck); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_getversion(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_DCS_CALL_GETVERSION, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_getversion_result( - void *_srpc, char SoftVer[SUPLA_SOFTVER_MAXSIZE]) { - TSDC_SuplaGetVersionResult gvr; - - gvr.proto_version = SUPLA_PROTO_VERSION; - gvr.proto_version_min = SUPLA_PROTO_VERSION_MIN; - - memcpy(gvr.SoftVer, SoftVer, SUPLA_SOFTVER_MAXSIZE); - - return srpc_async_call(_srpc, SUPLA_SDC_CALL_GETVERSION_RESULT, (char *)&gvr, - sizeof(TSDC_SuplaGetVersionResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sdc_async_versionerror(void *_srpc, unsigned char remote_version) { - TSDC_SuplaVersionError ve; - ve.server_version = SUPLA_PROTO_VERSION; - ve.server_version_min = SUPLA_PROTO_VERSION_MIN; - - return srpc_async__call(_srpc, SUPLA_SDC_CALL_VERSIONERROR, (char *)&ve, - sizeof(TSDC_SuplaVersionError), &remote_version); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_ping_server(void *_srpc) { - TDCS_SuplaPingServer ps; - -#if defined(ESP8266) - unsigned int time = system_get_time(); - ps.now.tv_sec = time / 1000000; - ps.now.tv_usec = time % 1000000; -#elif defined(__AVR__) - ps.now.tv_sec[0] = 0; - ps.now.tv_sec[1] = 0; - ps.now.tv_usec[0] = 0; - ps.now.tv_usec[1] = 0; -#else - struct timeval now; - gettimeofday(&now, NULL); - ps.now.tv_sec = now.tv_sec; - ps.now.tv_usec = now.tv_usec; -#endif - - return srpc_async_call(_srpc, SUPLA_DCS_CALL_PING_SERVER, (char *)&ps, - sizeof(TDCS_SuplaPingServer)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_ping_server_result(void *_srpc) { -#if !defined(ESP8266) && !defined(__AVR__) && !defined(ESP32) - TSDC_SuplaPingServerResult ps; - - struct timeval now; - gettimeofday(&now, NULL); - ps.now.tv_sec = now.tv_sec; - ps.now.tv_usec = now.tv_usec; - - return srpc_async_call(_srpc, SUPLA_SDC_CALL_PING_SERVER_RESULT, (char *)&ps, - sizeof(TSDC_SuplaPingServerResult)); -#else - return 0; -#endif -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout( - void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) { - return srpc_async_call(_srpc, SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT, - (char *)dcs_set_activity_timeout, - sizeof(TDCS_SuplaSetActivityTimeout)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout_result( - void *_srpc, - TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result) { - return srpc_async_call(_srpc, SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT, - (char *)sdc_set_activity_timeout_result, - sizeof(TSDC_SuplaSetActivityTimeoutResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_dcs_async_get_registration_enabled(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED, NULL, - 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_registration_enabled_result( - void *_srpc, TSDC_RegistrationEnabled *reg_enabled) { - return srpc_async_call(_srpc, SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT, - (char *)reg_enabled, sizeof(TSDC_RegistrationEnabled)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_get_user_localtime(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_USER_LOCALTIME, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_user_localtime_result( - void *_srpc, TSDC_UserLocalTimeResult *localtime) { - if (localtime == NULL || localtime->timezoneSize > SUPLA_TIMEZONE_MAXSIZE) { - return 0; - } - - unsigned int size = sizeof(TSDC_UserLocalTimeResult) - - SUPLA_TIMEZONE_MAXSIZE + localtime->timezoneSize; - - return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT, - (char *)localtime, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_csd_async_get_channel_state( - void *_srpc, TCSD_ChannelStateRequest *request) { - return srpc_async_call(_srpc, SUPLA_CSD_CALL_GET_CHANNEL_STATE, - (char *)request, sizeof(TCSD_ChannelStateRequest)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) { - return srpc_async_call(_srpc, SUPLA_DSC_CALL_CHANNEL_STATE_RESULT, - (char *)state, sizeof(TDSC_ChannelState)); -} - -#ifndef SRPC_EXCLUDE_DEVICE -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url( - void *_srpc, TDS_FirmwareUpdateParams *params) { - return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL, - (char *)params, sizeof(TDS_FirmwareUpdateParams)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice( - void *_srpc, TDS_SuplaRegisterDevice *registerdevice) { - _supla_int_t size = - sizeof(TDS_SuplaRegisterDevice) - - (sizeof(TDS_SuplaDeviceChannel) * SUPLA_CHANNELMAXCOUNT) + - (sizeof(TDS_SuplaDeviceChannel) * registerdevice->channel_count); - - if (size > sizeof(TDS_SuplaRegisterDevice)) return 0; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE, - (char *)registerdevice, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_b( - void *_srpc, TDS_SuplaRegisterDevice_B *registerdevice) { - _supla_int_t size = - sizeof(TDS_SuplaRegisterDevice_B) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + - (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); - - if (size > sizeof(TDS_SuplaRegisterDevice_B)) return 0; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_B, - (char *)registerdevice, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_c( - void *_srpc, TDS_SuplaRegisterDevice_C *registerdevice) { - _supla_int_t size = - sizeof(TDS_SuplaRegisterDevice_C) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + - (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); - - if (size > sizeof(TDS_SuplaRegisterDevice_C)) return 0; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_C, - (char *)registerdevice, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_d( - void *_srpc, TDS_SuplaRegisterDevice_D *registerdevice) { - _supla_int_t size = - sizeof(TDS_SuplaRegisterDevice_D) - - (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + - (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); - - if (size > sizeof(TDS_SuplaRegisterDevice_D)) return 0; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_D, - (char *)registerdevice, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_e( - void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) { - _supla_int_t size = - sizeof(TDS_SuplaRegisterDevice_E) - - (sizeof(TDS_SuplaDeviceChannel_C) * SUPLA_CHANNELMAXCOUNT) + - (sizeof(TDS_SuplaDeviceChannel_C) * registerdevice->channel_count); - - if (size > sizeof(TDS_SuplaRegisterDevice_E)) return 0; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_E, - (char *)registerdevice, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_registerdevice_result( - void *_srpc, TSD_SuplaRegisterDeviceResult *registerdevice_result) { - return srpc_async_call(_srpc, SUPLA_SD_CALL_REGISTER_DEVICE_RESULT, - (char *)registerdevice_result, - sizeof(TSD_SuplaRegisterDeviceResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sd_async_set_channel_value(void *_srpc, TSD_SuplaChannelNewValue *value) { - return srpc_async_call(_srpc, SUPLA_SD_CALL_CHANNEL_SET_VALUE, (char *)value, - sizeof(TSD_SuplaChannelNewValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_set_channelgroup_value( - void *_srpc, TSD_SuplaChannelGroupNewValue *value) { - return srpc_async_call(_srpc, SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE, - (char *)value, sizeof(TSD_SuplaChannelGroupNewValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, - _supla_int_t SenderID, char Success) { - TDS_SuplaChannelNewValueResult result; - result.ChannelNumber = ChannelNumber; - result.SenderID = SenderID; - result.Success = Success; - - return srpc_async_call(_srpc, SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT, - (char *)&result, - sizeof(TDS_SuplaChannelNewValueResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url_result( - void *_srpc, TSD_FirmwareUpdate_UrlResult *result) { - return srpc_async_call( - _srpc, SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT, (char *)result, - result->exists == 1 ? sizeof(TSD_FirmwareUpdate_UrlResult) - : sizeof(char)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed( - void *_srpc, unsigned char channel_number, char *value) { - TDS_SuplaDeviceChannelValue ncsc; - ncsc.ChannelNumber = channel_number; - memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); - - return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED, - (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_channel_value_changed_b(void *_srpc, unsigned char channel_number, - char *value, unsigned char offline) { - TDS_SuplaDeviceChannelValue_B ncsc; - ncsc.ChannelNumber = channel_number; - ncsc.Offline = !!offline; - memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); - - return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B, - (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue_B)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed_c( - void *_srpc, unsigned char channel_number, char *value, - unsigned char offline, unsigned _supla_int_t validity_time_sec) { - TDS_SuplaDeviceChannelValue_C ncsc; - ncsc.ChannelNumber = channel_number; - ncsc.Offline = !!offline; - ncsc.ValidityTimeSec = validity_time_sec; - memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); - - return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C, - (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue_C)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_extendedvalue_changed( - void *_srpc, unsigned char channel_number, - TSuplaChannelExtendedValue *value) { - if (value == NULL || value->size > SUPLA_CHANNELEXTENDEDVALUE_SIZE || - value->size == 0) { - return 0; - } - - TDS_SuplaDeviceChannelExtendedValue ncsc; - ncsc.ChannelNumber = channel_number; - memcpy(&ncsc.value, value, sizeof(TSuplaChannelExtendedValue)); - - return srpc_async_call( - _srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED, (char *)&ncsc, - sizeof(TDS_SuplaDeviceChannelExtendedValue) - - (SUPLA_CHANNELEXTENDEDVALUE_SIZE - ncsc.value.size)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_device_calcfg_request( - void *_srpc, TSD_DeviceCalCfgRequest *request) { - if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST, - (char *)request, - sizeof(TSD_DeviceCalCfgRequest) - - SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_device_calcfg_result( - void *_srpc, TDS_DeviceCalCfgResult *result) { - if (result == NULL || result->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CALCFG_RESULT, - (char *)result, - sizeof(TDS_DeviceCalCfgResult) - - SUPLA_CALCFG_DATA_MAXSIZE + result->DataSize); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_get_channel_functions(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_functions_result( - void *_srpc, TSD_ChannelFunctions *result) { - if (result == NULL || result->ChannelCount > SUPLA_CHANNELMAXCOUNT) { - return 0; - } - - _supla_int_t size = sizeof(TSD_ChannelFunctions) - - sizeof(_supla_int_t) * SUPLA_CHANNELMAXCOUNT + - sizeof(_supla_int_t) * result->ChannelCount; - - if (size > sizeof(TSD_ChannelFunctions)) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT, - (char *)result, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_config( - void *_srpc, TDS_GetChannelConfigRequest *request) { - if (request == NULL) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_CHANNEL_CONFIG, - (char *)request, sizeof(TDS_GetChannelConfigRequest)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_config_result( - void *_srpc, TSD_ChannelConfig *config) { - if (config == NULL || config->ConfigSize > SUPLA_CHANNEL_CONFIG_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT, - (char *)config, - sizeof(TSD_ChannelConfig) - - SUPLA_CHANNEL_CONFIG_MAXSIZE + config->ConfigSize); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_action_trigger(void *_srpc, TDS_ActionTrigger *action_trigger) { - if (action_trigger == NULL) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_DS_CALL_ACTIONTRIGGER, - (char *)action_trigger, sizeof(TDS_ActionTrigger)); -} - -#endif /*SRPC_EXCLUDE_DEVICE*/ - -#ifndef SRPC_EXCLUDE_CLIENT -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient( - void *_srpc, TCS_SuplaRegisterClient *registerclient) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT, - (char *)registerclient, - sizeof(TCS_SuplaRegisterClient)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_b( - void *_srpc, TCS_SuplaRegisterClient_B *registerclient) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_B, - (char *)registerclient, - sizeof(TCS_SuplaRegisterClient_B)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_c( - void *_srpc, TCS_SuplaRegisterClient_C *registerclient) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_C, - (char *)registerclient, - sizeof(TCS_SuplaRegisterClient_C)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_d( - void *_srpc, TCS_SuplaRegisterClient_D *registerclient) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_D, - (char *)registerclient, - sizeof(TCS_SuplaRegisterClient_D)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result( - void *_srpc, TSC_SuplaRegisterClientResult *registerclient_result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT, - (char *)registerclient_result, - sizeof(TSC_SuplaRegisterClientResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_b( - void *_srpc, TSC_SuplaRegisterClientResult_B *registerclient_result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B, - (char *)registerclient_result, - sizeof(TSC_SuplaRegisterClientResult_B)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_c( - void *_srpc, TSC_SuplaRegisterClientResult_C *registerclient_result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C, - (char *)registerclient_result, - sizeof(TSC_SuplaRegisterClientResult_C)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_location_update(void *_srpc, TSC_SuplaLocation *location) { - _supla_int_t size = sizeof(TSC_SuplaLocation) - - SUPLA_LOCATION_CAPTION_MAXSIZE + location->CaptionSize; - - if (size > sizeof(TSC_SuplaLocation)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_LOCATION_UPDATE, (char *)location, - size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_set_pack( - void *_srpc, void *pack, _supla_int_t count, - _func_srpc_pack_get_caption_size get_caption_size, - _func_srpc_pack_get_item_ptr get_item_ptr, - _func_srpc_pack_set_pack_count set_pack_count, - unsigned _supla_int_t pack_sizeof, unsigned _supla_int_t pack_max_count, - unsigned _supla_int_t caption_max_size, unsigned _supla_int_t item_sizeof, - unsigned _supla_int_t call_type) { - _supla_int_t result = 0; - _supla_int_t a; - _supla_int_t n = 0; - _supla_int_t size = 0; - _supla_int_t offset = 0; - - if (count < 1 || count > pack_max_count) return 0; - - size = pack_sizeof - (item_sizeof * pack_max_count); - offset = size; - - char *buffer = malloc(size); - - if (buffer == NULL) return 0; - - memcpy(buffer, pack, size); - - for (a = 0; a < count; a++) { - if (get_caption_size(pack, a) <= caption_max_size) { - size += item_sizeof - caption_max_size + get_caption_size(pack, a); - - char *new_buffer = (char *)realloc(buffer, size); - - if (new_buffer == NULL) { - free(buffer); - return 0; - } - - buffer = new_buffer; - memcpy(&buffer[offset], get_item_ptr(pack, a), size - offset); - offset += size - offset; - n++; - } - } - - set_pack_count(buffer, n, 0); - - result = srpc_async_call(_srpc, call_type, buffer, size); - - free(buffer); - return result; -} - -unsigned _supla_int_t srpc_locationpack_get_caption_size(void *pack, - _supla_int_t idx) { - return ((TSC_SuplaLocationPack *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_locationpack_update( - void *_srpc, TSC_SuplaLocationPack *location_pack) { - return srpc_set_pack( - _srpc, location_pack, location_pack->count, - &srpc_locationpack_get_caption_size, &srpc_locationpack_get_item_ptr, - &srpc_locationpack_set_pack_count, sizeof(TSC_SuplaLocationPack), - SUPLA_LOCATIONPACK_MAXCOUNT, SUPLA_LOCATION_CAPTION_MAXSIZE, - sizeof(TSC_SuplaLocation), SUPLA_SC_CALL_LOCATIONPACK_UPDATE); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_channel_update(void *_srpc, TSC_SuplaChannel *channel) { - _supla_int_t size = sizeof(TSC_SuplaChannel) - SUPLA_CHANNEL_CAPTION_MAXSIZE + - channel->CaptionSize; - - if (size > sizeof(TSC_SuplaChannel)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE, (char *)channel, - size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_channel_update_b(void *_srpc, TSC_SuplaChannel_B *channel_b) { - _supla_int_t size = sizeof(TSC_SuplaChannel_B) - - SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_b->CaptionSize; - - if (size > sizeof(TSC_SuplaChannel_B)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_B, - (char *)channel_b, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_channel_update_c(void *_srpc, TSC_SuplaChannel_C *channel_c) { - _supla_int_t size = sizeof(TSC_SuplaChannel_C) - - SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_c->CaptionSize; - - if (size > sizeof(TSC_SuplaChannel_C)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_C, - (char *)channel_c, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_channel_update_d(void *_srpc, TSC_SuplaChannel_D *channel_d) { - _supla_int_t size = sizeof(TSC_SuplaChannel_D) - - SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_d->CaptionSize; - - if (size > sizeof(TSC_SuplaChannel_D)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_D, - (char *)channel_d, size); -} - -unsigned _supla_int_t srpc_channelpack_get_caption_size(void *pack, - _supla_int_t idx) { - return ((TSC_SuplaChannelPack *)pack)->items[idx].CaptionSize; -} - -unsigned _supla_int_t srpc_channelpack_get_caption_size_b(void *pack, - _supla_int_t idx) { - return ((TSC_SuplaChannelPack_B *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update( - void *_srpc, TSC_SuplaChannelPack *channel_pack) { - return srpc_set_pack( - _srpc, channel_pack, channel_pack->count, - &srpc_channelpack_get_caption_size, &srpc_channelpack_get_item_ptr, - &srpc_channelpack_set_pack_count, sizeof(TSC_SuplaChannelPack), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - sizeof(TSC_SuplaChannel), SUPLA_SC_CALL_CHANNELPACK_UPDATE); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_b( - void *_srpc, TSC_SuplaChannelPack_B *channel_pack) { - return srpc_set_pack( - _srpc, channel_pack, channel_pack->count, - &srpc_channelpack_get_caption_size_b, &srpc_channelpack_get_item_ptr_b, - &srpc_channelpack_set_pack_count_b, sizeof(TSC_SuplaChannelPack_B), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - sizeof(TSC_SuplaChannel_B), SUPLA_SC_CALL_CHANNELPACK_UPDATE_B); -} - -unsigned _supla_int_t srpc_channelpack_get_caption_size_c(void *pack, - _supla_int_t idx) { - return ((TSC_SuplaChannelPack_C *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_c( - void *_srpc, TSC_SuplaChannelPack_C *channel_pack) { - return srpc_set_pack( - _srpc, channel_pack, channel_pack->count, - &srpc_channelpack_get_caption_size_c, &srpc_channelpack_get_item_ptr_c, - &srpc_channelpack_set_pack_count_c, sizeof(TSC_SuplaChannelPack_C), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - sizeof(TSC_SuplaChannel_C), SUPLA_SC_CALL_CHANNELPACK_UPDATE_C); -} - -unsigned _supla_int_t srpc_channelpack_get_caption_size_d(void *pack, - _supla_int_t idx) { - return ((TSC_SuplaChannelPack_D *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_d( - void *_srpc, TSC_SuplaChannelPack_D *channel_pack) { - return srpc_set_pack( - _srpc, channel_pack, channel_pack->count, - &srpc_channelpack_get_caption_size_d, &srpc_channelpack_get_item_ptr_d, - &srpc_channelpack_set_pack_count_d, sizeof(TSC_SuplaChannelPack_D), - SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, - sizeof(TSC_SuplaChannel_D), SUPLA_SC_CALL_CHANNELPACK_UPDATE_D); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update( - void *_srpc, TSC_SuplaChannelValue *channel_value) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE, - (char *)channel_value, sizeof(TSC_SuplaChannelValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update_b( - void *_srpc, TSC_SuplaChannelValue_B *channel_value) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B, - (char *)channel_value, - sizeof(TSC_SuplaChannelValue_B)); -} - -unsigned _supla_int_t -srpc_channelgroup_pack_get_caption_size(void *pack, _supla_int_t idx) { - return ((TSC_SuplaChannelGroupPack *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update( - void *_srpc, TSC_SuplaChannelGroupPack *channelgroup_pack) { - return srpc_set_pack( - _srpc, channelgroup_pack, channelgroup_pack->count, - &srpc_channelgroup_pack_get_caption_size, - &srpc_channelgroup_pack_get_item_ptr, - &srpc_channelgroup_pack_set_pack_count, sizeof(TSC_SuplaChannelGroupPack), - SUPLA_CHANNELGROUP_PACK_MAXCOUNT, SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, - sizeof(TSC_SuplaChannelGroup), SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE); -} - -unsigned _supla_int_t -srpc_channelgroup_pack_b_get_caption_size(void *pack, _supla_int_t idx) { - return ((TSC_SuplaChannelGroupPack_B *)pack)->items[idx].CaptionSize; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update_b( - void *_srpc, TSC_SuplaChannelGroupPack_B *channelgroup_pack) { - return srpc_set_pack( - _srpc, channelgroup_pack, channelgroup_pack->count, - &srpc_channelgroup_pack_b_get_caption_size, - &srpc_channelgroup_pack_b_get_item_ptr, - &srpc_channelgroup_pack_b_set_pack_count, - sizeof(TSC_SuplaChannelGroupPack_B), SUPLA_CHANNELGROUP_PACK_MAXCOUNT, - SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, sizeof(TSC_SuplaChannelGroup_B), - SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_relation_pack_update( - void *_srpc, - TSC_SuplaChannelGroupRelationPack *channelgroup_relation_pack) { - if (channelgroup_relation_pack->count < 1 || - channelgroup_relation_pack->count > - SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT) { - return 0; - } - - unsigned _supla_int_t size = sizeof(TSC_SuplaChannelGroupRelationPack) - - sizeof(channelgroup_relation_pack->items) + - (sizeof(TSC_SuplaChannelGroupRelation) * - channelgroup_relation_pack->count); - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE, - (char *)channelgroup_relation_pack, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update( - void *_srpc, TSC_SuplaChannelValuePack *channelvalue_pack) { - if (channelvalue_pack->count < 1 || - channelvalue_pack->count > SUPLA_CHANNELVALUE_PACK_MAXCOUNT) { - return 0; - } - - unsigned _supla_int_t size = - sizeof(TSC_SuplaChannelValuePack) - sizeof(channelvalue_pack->items) + - (sizeof(TSC_SuplaChannelValue) * channelvalue_pack->count); - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE, - (char *)channelvalue_pack, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update_b( - void *_srpc, TSC_SuplaChannelValuePack_B *channelvalue_pack) { - if (channelvalue_pack->count < 1 || - channelvalue_pack->count > SUPLA_CHANNELVALUE_PACK_MAXCOUNT) { - return 0; - } - - unsigned _supla_int_t size = - sizeof(TSC_SuplaChannelValuePack_B) - sizeof(channelvalue_pack->items) + - (sizeof(TSC_SuplaChannelValue_B) * channelvalue_pack->count); - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B, - (char *)channelvalue_pack, size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelextendedvalue_pack_update( - void *_srpc, TSC_SuplaChannelExtendedValuePack *extendedvalue_pack) { - if (extendedvalue_pack == NULL || extendedvalue_pack->count < 1 || - extendedvalue_pack->count > SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXCOUNT || - extendedvalue_pack->pack_size < 1 || - extendedvalue_pack->pack_size > - SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE, - (char *)extendedvalue_pack, - sizeof(TSC_SuplaChannelExtendedValuePack) - - SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE + - extendedvalue_pack->pack_size); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_get_next(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_GET_NEXT, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_event(void *_srpc, - TSC_SuplaEvent *event) { - _supla_int_t size = sizeof(TSC_SuplaEvent) - SUPLA_SENDER_NAME_MAXSIZE + - event->SenderNameSize; - - if (size > sizeof(TSC_SuplaEvent)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_EVENT, (char *)event, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_value(void *_srpc, TCS_SuplaChannelNewValue *value) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_CHANNEL_SET_VALUE, (char *)value, - sizeof(TCS_SuplaChannelNewValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_channel_value_b( - void *_srpc, TCS_SuplaChannelNewValue_B *value) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_CHANNEL_SET_VALUE_B, - (char *)value, sizeof(TCS_SuplaChannelNewValue_B)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_value(void *_srpc, TCS_SuplaNewValue *value) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_VALUE, (char *)value, - sizeof(TCS_SuplaNewValue)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request_result( - void *_srpc, TSC_OAuthTokenRequestResult *result) { - if (result == NULL || result->Token.TokenSize > SUPLA_OAUTH_TOKEN_MAXSIZE) { - return 0; - } - - return srpc_async_call( - _srpc, SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT, (char *)result, - sizeof(TSC_OAuthTokenRequestResult) - - (SUPLA_OAUTH_TOKEN_MAXSIZE - result->Token.TokenSize)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_superuser_authorization_request( - void *_srpc, TCS_SuperUserAuthorizationRequest *request) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST, - (char *)request, - sizeof(TCS_SuperUserAuthorizationRequest)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_get_superuser_authorization_result(void *_srpc) { - return srpc_async_call( - _srpc, SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT, NULL, 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_superuser_authorization_result( - void *_srpc, TSC_SuperUserAuthorizationResult *result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT, - (char *)result, - sizeof(TSC_SuperUserAuthorizationResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request( - void *_srpc, TCS_DeviceCalCfgRequest *request) { - if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST, - (char *)request, - sizeof(TCS_DeviceCalCfgRequest) - - SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request_b( - void *_srpc, TCS_DeviceCalCfgRequest_B *request) { - if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B, - (char *)request, - sizeof(TCS_DeviceCalCfgRequest_B) - - SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_calcfg_result( - void *_srpc, TSC_DeviceCalCfgResult *result) { - if (result == NULL || result->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { - return 0; - } - - return srpc_async_call(_srpc, SUPLA_SC_CALL_DEVICE_CALCFG_RESULT, - (char *)result, - sizeof(TSC_DeviceCalCfgResult) - - SUPLA_CALCFG_DATA_MAXSIZE + result->DataSize); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_get_channel_basic_cfg(void *_srpc, _supla_int_t ChannelID) { - TCS_ChannelBasicCfgRequest request; - memset(&request, 0, sizeof(TCS_ChannelBasicCfgRequest)); - request.ChannelID = ChannelID; - - return srpc_async_call(_srpc, SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG, - (char *)&request, sizeof(TCS_ChannelBasicCfgRequest)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_basic_cfg_result( - void *_srpc, TSC_ChannelBasicCfg *basic_cfg) { - _supla_int_t size = sizeof(TSC_ChannelBasicCfg) - - SUPLA_CHANNEL_CAPTION_MAXSIZE + basic_cfg->CaptionSize; - - if (size > sizeof(TSC_ChannelBasicCfg)) return 0; - - return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT, - (char *)basic_cfg, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_function(void *_srpc, TCS_SetChannelFunction *func) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_CHANNEL_FUNCTION, - (char *)func, sizeof(TCS_SetChannelFunction)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_function_result( - void *_srpc, TSC_SetChannelFunctionResult *result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT, - (char *)result, sizeof(TSC_SetChannelFunctionResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_caption( - void *_srpc, TCS_SetCaption *caption, unsigned _supla_int_t call_type) { - _supla_int_t size = - sizeof(TCS_SetCaption) - SUPLA_CAPTION_MAXSIZE + caption->CaptionSize; - - if (size > sizeof(TCS_SetCaption)) return 0; - - return srpc_async_call(_srpc, call_type, (char *)caption, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_set_caption_result(void *_srpc, TSC_SetCaptionResult *result, - unsigned _supla_int_t call_type) { - _supla_int_t size = sizeof(TSC_SetCaptionResult) - SUPLA_CAPTION_MAXSIZE + - result->CaptionSize; - - if (size > sizeof(TSC_SetCaptionResult)) return 0; - - return srpc_async_call(_srpc, call_type, (char *)result, size); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_caption(void *_srpc, TCS_SetCaption *caption) { - return srpc_cs_async_set_caption(_srpc, caption, - SUPLA_CS_CALL_SET_CHANNEL_CAPTION); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_caption_result( - void *_srpc, TSC_SetCaptionResult *result) { - return srpc_sc_async_set_caption_result( - _srpc, result, SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_location_caption(void *_srpc, TCS_SetCaption *caption) { - return srpc_cs_async_set_caption(_srpc, caption, - SUPLA_CS_CALL_SET_LOCATION_CAPTION); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_location_caption_result( - void *_srpc, TSC_SetCaptionResult *result) { - return srpc_sc_async_set_caption_result( - _srpc, result, SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_clients_reconnect_request(void *_srpc) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST, NULL, - 0); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_clients_reconnect_request_result( - void *_srpc, TSC_ClientsReconnectRequestResult *result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT, - (char *)result, - sizeof(TSC_ClientsReconnectRequestResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_registration_enabled( - void *_srpc, TCS_SetRegistrationEnabled *reg_enabled) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_REGISTRATION_ENABLED, - (char *)reg_enabled, - sizeof(TCS_SetRegistrationEnabled)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_registration_enabled_result( - void *_srpc, TSC_SetRegistrationEnabledResult *result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT, - (char *)result, - sizeof(TSC_SetRegistrationEnabledResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_reconnect_request( - void *_srpc, TCS_DeviceReconnectRequest *request) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST, - (char *)request, sizeof(TCS_DeviceReconnectRequest)); -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_reconnect_request_result( - void *_srpc, TSC_DeviceReconnectRequestResult *result) { - return srpc_async_call(_srpc, SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT, - (char *)result, - sizeof(TSC_DeviceReconnectRequestResult)); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_timer_arm(void *_srpc, TCS_TimerArmRequest *request) { - return srpc_async_call(_srpc, SUPLA_CS_CALL_TIMER_ARM, (char *)request, - sizeof(TCS_TimerArmRequest)); -} - -#endif /*SRPC_EXCLUDE_CLIENT*/ - -#ifndef SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS - -#ifdef USE_DEPRECATED_EMEV_V1 -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_emextended2extended( - TElectricityMeter_ExtendedValue *em_ev, TSuplaChannelExtendedValue *ev) { - if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || - em_ev->m_count < 0) { - return 0; - } - - memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); - ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1; - - ev->size = sizeof(TElectricityMeter_ExtendedValue) - - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + - sizeof(TElectricityMeter_Measurement) * em_ev->m_count; - - if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { - memcpy(ev->value, em_ev, ev->size); - return 1; - } - - ev->size = 0; - return 0; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2emextended( - TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue *em_ev) { - if (em_ev == NULL || ev == NULL || - ev->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1 || ev->size == 0 || - ev->size > sizeof(TElectricityMeter_ExtendedValue)) { - return 0; - } - - memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue)); - memcpy(em_ev, ev->value, ev->size); - - _supla_int_t expected_size = 0; - - if (em_ev->m_count <= EM_MEASUREMENT_COUNT) { - expected_size = - sizeof(TElectricityMeter_ExtendedValue) - - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + - sizeof(TElectricityMeter_Measurement) * em_ev->m_count; - } - - if (ev->size != expected_size) { - memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue)); - return 0; - } - - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_emev_v1to2(TElectricityMeter_ExtendedValue *v1, - TElectricityMeter_ExtendedValue_V2 *v2) { - if (v1 == NULL || v2 == NULL) { - return 0; - } - memset(v2, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); - - for (int a = 0; a < 3; a++) { - v2->total_forward_active_energy[a] = v1->total_forward_active_energy[a]; - v2->total_reverse_active_energy[a] = v1->total_reverse_active_energy[a]; - v2->total_forward_reactive_energy[a] = v1->total_forward_reactive_energy[a]; - v2->total_reverse_reactive_energy[a] = v1->total_reverse_reactive_energy[a]; - } - - v2->total_cost = v1->total_cost; - v2->price_per_unit = v1->price_per_unit; - memcpy(v2->currency, v1->currency, sizeof(v2->currency)); - v2->measured_values = v1->measured_values; - v2->period = v1->period; - v2->m_count = v1->m_count; - - memcpy(v2->m, v1->m, - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT); - - v2->measured_values ^= - v1->measured_values & EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED; - v2->measured_values ^= - v1->measured_values & EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED; - - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_emev_v2to1(TElectricityMeter_ExtendedValue_V2 *v2, - TElectricityMeter_ExtendedValue *v1) { - if (v1 == NULL || v2 == NULL) { - return 0; - } - memset(v1, 0, sizeof(TElectricityMeter_ExtendedValue)); - - for (int a = 0; a < 3; a++) { - v1->total_forward_active_energy[a] = v2->total_forward_active_energy[a]; - v1->total_reverse_active_energy[a] = v2->total_reverse_active_energy[a]; - v1->total_forward_reactive_energy[a] = v2->total_forward_reactive_energy[a]; - v1->total_reverse_reactive_energy[a] = v2->total_reverse_reactive_energy[a]; - } - - v1->total_cost = v2->total_cost; - v1->price_per_unit = v2->price_per_unit; - memcpy(v1->currency, v2->currency, sizeof(v2->currency)); - v1->measured_values = v2->measured_values; - v1->period = v2->period; - v1->m_count = v2->m_count; - - memcpy(v1->m, v2->m, - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT); - - v1->measured_values ^= - v1->measured_values & EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED; - v1->measured_values ^= - v1->measured_values & EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED; - - return 1; -} - -#endif /*USE_DEPRECATED_EMEV_V1*/ - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_emextended2extended( - TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev) { - if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || - em_ev->m_count < 0) { - return 0; - } - - memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); - ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2; - - ev->size = sizeof(TElectricityMeter_ExtendedValue_V2) - - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + - sizeof(TElectricityMeter_Measurement) * em_ev->m_count; - - if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { - memcpy(ev->value, em_ev, ev->size); - return 1; - } - - ev->size = 0; - return 0; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_extended2emextended( - TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue_V2 *em_ev) { - if (em_ev == NULL || ev == NULL || - ev->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2 || ev->size == 0 || - ev->size > sizeof(TElectricityMeter_ExtendedValue_V2)) { - return 0; - } - - memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); - memcpy(em_ev, ev->value, ev->size); - - _supla_int_t expected_size = 0; - - if (em_ev->m_count <= EM_MEASUREMENT_COUNT) { - expected_size = - sizeof(TElectricityMeter_ExtendedValue_V2) - - sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + - sizeof(TElectricityMeter_Measurement) * em_ev->m_count; - } - - if (ev->size != expected_size) { - memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); - return 0; - } - - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2thermostatextended( - TSuplaChannelExtendedValue *ev, TThermostat_ExtendedValue *th_ev) { - if (ev == NULL || th_ev == NULL || - ev->type != EV_TYPE_THERMOSTAT_DETAILS_V1 || ev->size == 0 || - ev->size > sizeof(TThermostat_ExtendedValue)) { - return 0; - } - - memset(th_ev, 0, sizeof(TThermostat_ExtendedValue)); - memcpy(th_ev, ev->value, ev->size); - - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_thermostatextended2extended( - TThermostat_ExtendedValue *th_ev, TSuplaChannelExtendedValue *ev) { - if (th_ev == NULL || ev == NULL) { - return 0; - } - - memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); - ev->type = EV_TYPE_THERMOSTAT_DETAILS_V1; - ev->size = 0; - - unsigned _supla_int_t size = sizeof(TThermostat_ExtendedValue); - - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Schedule)) { - size -= sizeof(th_ev->Schedule); - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Time)) { - size -= sizeof(th_ev->Time); - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Values)) { - size -= sizeof(th_ev->Values); - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Flags)) { - size -= sizeof(th_ev->Flags); - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_PresetTemperatures)) { - size -= sizeof(th_ev->PresetTemperature); - if (0 == (th_ev->Fields & THERMOSTAT_FIELD_MeasuredTemperatures)) { - size -= sizeof(th_ev->MeasuredTemperature); - } - } - } - } - } - } - - if (size > 0) { - ev->size = size; - memcpy(ev->value, th_ev, size); - return 1; - } - - return 0; -} - -#ifndef SRPC_EXCLUDE_CLIENT -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_icextended2extended( - TSC_ImpulseCounter_ExtendedValue *ic_ev, TSuplaChannelExtendedValue *ev) { - if (ic_ev == NULL || ev == NULL) { - return 0; - } - - memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); - ev->type = EV_TYPE_IMPULSE_COUNTER_DETAILS_V1; - ev->size = sizeof(TSC_ImpulseCounter_ExtendedValue); - - memcpy(ev->value, ic_ev, ev->size); - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2icextended( - TSuplaChannelExtendedValue *ev, TSC_ImpulseCounter_ExtendedValue *ic_ev) { - if (ic_ev == NULL || ev == NULL || - ev->type != EV_TYPE_IMPULSE_COUNTER_DETAILS_V1 || ev->size == 0 || - ev->size != sizeof(TSC_ImpulseCounter_ExtendedValue)) { - return 0; - } - - memset(ic_ev, 0, sizeof(TSC_ImpulseCounter_ExtendedValue)); - memcpy(ic_ev, ev->value, ev->size); - - return 1; -} - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_value_add( - TSuplaChannelExtendedValue *dest, TSuplaChannelExtendedValue *src) { - if (!dest || !src) { - return 0; - } - - if (src->type == EV_TYPE_NONE || src->size == 0) { - return 0; - } - - if (dest->type == EV_TYPE_NONE) { - memcpy(dest, src, sizeof(TSuplaChannelExtendedValue)); - return 1; - } - - unsigned int src_size = - sizeof(TSuplaChannelExtendedValue) - (sizeof(src->value) - src->size); - - if (dest->type == EV_TYPE_MULTI_VALUE) { - if (dest->size + src_size > sizeof(dest->value)) { - return 0; - } - - memcpy(&dest->value[dest->size], src, src_size); - dest->size += src_size; - return 1; - } - - unsigned int prev_size = - sizeof(TSuplaChannelExtendedValue) - (sizeof(dest->value) - dest->size); - - if (prev_size + src_size > sizeof(dest->value)) { - return 0; - } - - TSuplaChannelExtendedValue prev = {}; - memcpy(&prev, dest, sizeof(TSuplaChannelExtendedValue)); - - dest->type = EV_TYPE_MULTI_VALUE; - dest->size = prev_size; - - memcpy(dest->value, &prev, prev_size); - - return srpc_evtool_value_add(dest, src); -} - -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_value_get(TSuplaChannelExtendedValue *ev, unsigned short index, - TSuplaChannelExtendedValue *dest) { - if (dest == NULL || ev == NULL || ev->type == EV_TYPE_NONE) { - return 0; - } - - if (ev->type == EV_TYPE_MULTI_VALUE) { - unsigned int header_size = - sizeof(TSuplaChannelExtendedValue) - sizeof(ev->value); - unsigned int offset = 0; - unsigned int size = ev->size; - if (size > sizeof(ev->value)) { - size = sizeof(ev->value); - } - size -= header_size; - - unsigned short n = 0; - - while (offset < size) { - TSuplaChannelExtendedValue *next = - (TSuplaChannelExtendedValue *)&ev->value[offset]; - - if (next->type == EV_TYPE_NONE || next->size == 0 || - next->size + offset + header_size > sizeof(ev->value)) { - return 0; - } - - if (n == index) { - memcpy(dest, next, header_size + next->size); - return 1; - } - - offset += header_size + next->size; - n++; - } - } - - if (index == 0) { - memcpy(dest, ev, sizeof(TSuplaChannelExtendedValue)); - return 1; - } - - return 0; -} - -#endif /*SRPC_EXCLUDE_CLIENT*/ - -#endif /*SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "srpc.h" + +#include +#include + +#include "lck.h" +#include "log.h" +#include "proto.h" + +#if defined(ESP8266) || defined(ESP32) + +#include +#if !defined(ESP32) +#include +#endif + +#if defined(ARDUINO_ARCH_ESP8266) +#include +#define __EH_DISABLED +#elif defined(ARDUINO_ARCH_ESP32) +#define __EH_DISABLED +#else +#include + +#include "espmissingincludes.h" +#endif + +#ifndef SRPC_BUFFER_SIZE +#define SRPC_BUFFER_SIZE 1024 +#endif /*SRPC_BUFFER_SIZE*/ + +#ifndef SRPC_QUEUE_SIZE +#define SRPC_QUEUE_SIZE 2 +#endif /*SRPC_QUEUE_SIZE*/ + +#ifndef SRPC_QUEUE_MIN_ALLOC_COUNT +#define SRPC_QUEUE_MIN_ALLOC_COUNT 2 +#endif /* SRPC_QUEUE_MIN_ALLOC_COUNT */ + +#elif defined(__AVR__) + +#define SRPC_BUFFER_SIZE 32 +#define SRPC_QUEUE_SIZE 1 +#define SRPC_QUEUE_MIN_ALLOC_COUNT 1 +#define __EH_DISABLED + +#else +#include +#endif + +#ifndef SRPC_BUFFER_SIZE +#define SRPC_BUFFER_SIZE 32768 +#endif /*SRPC_BUFFER_SIZE*/ + +#ifndef SRPC_QUEUE_SIZE +#define SRPC_QUEUE_SIZE 10 +#endif /*SRPC_QUEUE_SIZE*/ + +#ifndef SRPC_QUEUE_MIN_ALLOC_COUNT +#define SRPC_QUEUE_MIN_ALLOC_COUNT 0 +#endif /*SRPC_QUEUE_MIN_ALLOC_COUNT*/ + +typedef struct { + unsigned char item_count; + unsigned char alloc_count; + + TSuplaDataPacket *item[SRPC_QUEUE_SIZE]; +} Tsrpc_Queue; + +typedef struct { + void *proto; + TsrpcParams params; + + TSuplaDataPacket sdp; + +#ifndef SRPC_WITHOUT_IN_QUEUE + Tsrpc_Queue in_queue; +#endif /*SRPC_WITHOUT_IN_QUEUE*/ + +#ifndef SRPC_WITHOUT_OUT_QUEUE + Tsrpc_Queue out_queue; +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ + + void *lck; +} Tsrpc; + +void SRPC_ICACHE_FLASH srpc_params_init(TsrpcParams *params) { + memset(params, 0, sizeof(TsrpcParams)); +} + +void *SRPC_ICACHE_FLASH srpc_init(TsrpcParams *params) { + Tsrpc *srpc = (Tsrpc *)malloc(sizeof(Tsrpc)); + + if (srpc == NULL) return NULL; + + memset(srpc, 0, sizeof(Tsrpc)); + srpc->proto = sproto_init(); + +#ifndef ESP8266 +#ifndef ESP32 +#ifndef __AVR__ + assert(params != 0); + assert(params->data_read != 0); + assert(params->data_write != 0); +#endif +#endif +#endif + + memcpy(&srpc->params, params, sizeof(TsrpcParams)); + + srpc->lck = lck_init(); + + return srpc; +} + +void SRPC_ICACHE_FLASH srpc_queue_free(Tsrpc_Queue *queue) { + _supla_int_t a; + for (a = 0; a < SRPC_QUEUE_SIZE; a++) { + if (queue->item[a] != NULL) { + free(queue->item[a]); + } + } + + queue->item_count = 0; + queue->alloc_count = 0; +} + +void SRPC_ICACHE_FLASH srpc_free(void *_srpc) { + if (_srpc) { + Tsrpc *srpc = (Tsrpc *)_srpc; + + sproto_free(srpc->proto); + +#ifndef SRPC_WITHOUT_IN_QUEUE + srpc_queue_free(&srpc->in_queue); +#endif /*SRPC_WITHOUT_IN_QUEUE*/ + +#ifndef SRPC_WITHOUT_OUT_QUEUE + srpc_queue_free(&srpc->out_queue); +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ + lck_free(srpc->lck); + + free(srpc); + } +} + +char SRPC_ICACHE_FLASH srpc_queue_push(Tsrpc_Queue *queue, + TSuplaDataPacket *sdp) { + if (queue->item_count >= SRPC_QUEUE_SIZE) { + return SUPLA_RESULT_FALSE; + } + + if (queue->item[queue->item_count] == NULL) { + queue->item[queue->item_count] = + (TSuplaDataPacket *)malloc(sizeof(TSuplaDataPacket)); + } + + if (queue->item[queue->item_count] == NULL) { + return SUPLA_RESULT_FALSE; + } else { + queue->alloc_count++; + } + + memcpy(queue->item[queue->item_count], sdp, sizeof(TSuplaDataPacket)); + queue->item_count++; + + return SUPLA_RESULT_TRUE; +} + +char SRPC_ICACHE_FLASH srpc_queue_pop(Tsrpc_Queue *queue, TSuplaDataPacket *sdp, + unsigned _supla_int_t rr_id) { + _supla_int_t a, b; + + for (a = 0; a < queue->item_count; a++) + if (rr_id == 0 || queue->item[a]->rr_id == rr_id) { + memcpy(sdp, queue->item[a], sizeof(TSuplaDataPacket)); + + if (queue->alloc_count > SRPC_QUEUE_MIN_ALLOC_COUNT) { + queue->alloc_count--; + free(queue->item[a]); + queue->item[a] = NULL; + } + + TSuplaDataPacket *item = queue->item[a]; + + for (b = a; b < queue->item_count - 1; b++) { + queue->item[b] = queue->item[b + 1]; + } + + queue->item_count--; + queue->item[queue->item_count] = item; + + return SUPLA_RESULT_TRUE; + } + + return SUPLA_RESULT_FALSE; +} + +char SRPC_ICACHE_FLASH srpc_in_queue_pop(Tsrpc *srpc, TSuplaDataPacket *sdp, + unsigned _supla_int_t rr_id) { +#ifdef SRPC_WITHOUT_IN_QUEUE + return 1; +#else + return srpc_queue_pop(&srpc->in_queue, sdp, rr_id); +#endif /*SRPC_WITHOUT_IN_QUEUE*/ +} + +#ifndef SRPC_WITHOUT_IN_QUEUE +char SRPC_ICACHE_FLASH srpc_in_queue_push(Tsrpc *srpc, TSuplaDataPacket *sdp) { + return srpc_queue_push(&srpc->in_queue, sdp); +} +#endif /*SRPC_WITHOUT_IN_QUEUE*/ + +char SRPC_ICACHE_FLASH srpc_out_queue_push(Tsrpc *srpc, TSuplaDataPacket *sdp) { +#ifdef SRPC_WITHOUT_OUT_QUEUE + unsigned _supla_int_t data_size = sizeof(TSuplaDataPacket); + if (sdp->data_size < SUPLA_MAX_DATA_SIZE) { + data_size -= SUPLA_MAX_DATA_SIZE - sdp->data_size; + } +#ifndef PACKET_INTEGRITY_BUFFER_DISABLED + char *buff = malloc(data_size + SUPLA_TAG_SIZE); + if (buff) { + memcpy(buff, sdp, data_size); + memcpy(&buff[data_size], sproto_tag, SUPLA_TAG_SIZE); + + srpc->params.data_write(buff, data_size + SUPLA_TAG_SIZE, + srpc->params.user_params); + free(buff); + } +#else + srpc->params.data_write((char *)sdp, data_size, srpc->params.user_params); + srpc->params.data_write(sproto_tag, SUPLA_TAG_SIZE, srpc->params.user_params); +#endif /*PACKET_INTEGRITY_BUFFER_DISABLED*/ + return 1; +#else + return srpc_queue_push(&srpc->out_queue, sdp); +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ +} + +#ifndef SRPC_WITHOUT_OUT_QUEUE +char SRPC_ICACHE_FLASH srpc_out_queue_pop(Tsrpc *srpc, TSuplaDataPacket *sdp, + unsigned _supla_int_t rr_id) { + return srpc_queue_pop(&srpc->out_queue, sdp, rr_id); +} +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ + +unsigned char SRPC_ICACHE_FLASH srpc_out_queue_item_count(void *srpc) { +#ifdef SRPC_WITHOUT_OUT_QUEUE + return 0; +#else + return ((Tsrpc *)srpc)->out_queue.item_count; +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ +} + +char SRPC_ICACHE_FLASH srpc_input_dataexists(void *_srpc) { + int result = SUPLA_RESULT_FALSE; + Tsrpc *srpc = (Tsrpc *)_srpc; + lck_lock(srpc->lck); + result = sproto_in_dataexists(srpc->proto); + return lck_unlock_r(srpc->lck, result); +} + +char SRPC_ICACHE_FLASH srpc_output_dataexists(void *_srpc) { + int result = SUPLA_RESULT_FALSE; + Tsrpc *srpc = (Tsrpc *)_srpc; + lck_lock(srpc->lck); + result = sproto_out_dataexists(srpc->proto); + return lck_unlock_r(srpc->lck, result); +} + +char SRPC_ICACHE_FLASH srpc_iterate(void *_srpc) { + Tsrpc *srpc = (Tsrpc *)_srpc; + char data_buffer[SRPC_BUFFER_SIZE]; + char result; + unsigned char version; +#ifndef __EH_DISABLED + unsigned char raise_event = 0; +#endif /*__EH_DISABLED*/ + + // --------- IN --------------- + _supla_int_t data_size = srpc->params.data_read(data_buffer, SRPC_BUFFER_SIZE, + srpc->params.user_params); + + if (data_size == 0) return SUPLA_RESULT_FALSE; + + lck_lock(srpc->lck); + + if (data_size > 0 && + SUPLA_RESULT_TRUE != (result = sproto_in_buffer_append( + srpc->proto, data_buffer, data_size))) { + supla_log(LOG_DEBUG, "sproto_in_buffer_append: %i, datasize: %i", result, + data_size); + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); + } + + if (SUPLA_RESULT_TRUE == + (result = sproto_pop_in_sdp(srpc->proto, &srpc->sdp))) { +#ifndef __EH_DISABLED + raise_event = sproto_in_dataexists(srpc->proto) == 1 ? 1 : 0; +#endif /*__EH_DISABLED*/ + +#ifdef SRPC_WITHOUT_IN_QUEUE + if (srpc->params.on_remote_call_received) { + lck_unlock(srpc->lck); + srpc->params.on_remote_call_received( + srpc, srpc->sdp.rr_id, srpc->sdp.call_type, srpc->params.user_params, + srpc->sdp.version); + lck_lock(srpc->lck); + } +#else + if (SUPLA_RESULT_TRUE == srpc_in_queue_push(srpc, &srpc->sdp)) { + if (srpc->params.on_remote_call_received) { + lck_unlock(srpc->lck); + srpc->params.on_remote_call_received( + srpc, srpc->sdp.rr_id, srpc->sdp.call_type, + srpc->params.user_params, srpc->sdp.version); + lck_lock(srpc->lck); + } + + } else { + supla_log(LOG_DEBUG, "ssrpc_in_queue_push error"); + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); + } +#endif /*SRPC_WITHOUT_IN_QUEUE*/ + + } else if (result != SUPLA_RESULT_FALSE) { + if (result == (char)SUPLA_RESULT_VERSION_ERROR) { + if (srpc->params.on_version_error) { + version = srpc->sdp.version; + lck_unlock(srpc->lck); + + srpc->params.on_version_error(srpc, version, srpc->params.user_params); + return SUPLA_RESULT_FALSE; + } + } else { + supla_log(LOG_DEBUG, "sproto_pop_in_sdp error: %i", result); + } + + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); + } + + // --------- OUT --------------- +#ifndef SRPC_WITHOUT_OUT_QUEUE + if (srpc_out_queue_pop(srpc, &srpc->sdp, 0) == SUPLA_RESULT_TRUE && + SUPLA_RESULT_TRUE != + (result = sproto_out_buffer_append(srpc->proto, &srpc->sdp)) && + result != SUPLA_RESULT_FALSE) { + supla_log(LOG_DEBUG, "sproto_out_buffer_append error: %i", result); + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); + } + + data_size = sproto_pop_out_data(srpc->proto, data_buffer, SRPC_BUFFER_SIZE); + + if (data_size != 0) { + lck_unlock(srpc->lck); + srpc->params.data_write(data_buffer, data_size, srpc->params.user_params); + lck_lock(srpc->lck); + } + +#ifndef __EH_DISABLED + if (srpc->params.eh != 0 && + (sproto_out_dataexists(srpc->proto) == 1 || + srpc_out_queue_item_count(srpc) || raise_event)) { + eh_raise_event(srpc->params.eh); + } +#endif /*__EH_DISABLED*/ + +#else /*SRPC_WITHOUT_OUT_QUEUE*/ +#ifndef __EH_DISABLED + if (srpc->params.eh != 0 && raise_event) { + eh_raise_event(srpc->params.eh); + } +#endif /*__EH_DISABLED*/ +#endif /*SRPC_WITHOUT_OUT_QUEUE*/ + return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); +} + +typedef unsigned _supla_int_t (*_func_srpc_pack_get_caption_size)( + void *pack, _supla_int_t idx); +typedef void *(*_func_srpc_pack_get_item_ptr)(void *pack, _supla_int_t idx); +typedef _supla_int_t (*_func_srpc_pack_get_pack_count)(void *pack); +typedef void (*_func_srpc_pack_set_pack_count)(void *pack, _supla_int_t count, + unsigned char increment); +typedef unsigned _supla_int_t (*_func_srpc_pack_get_item_caption_size)( + void *item); +typedef unsigned _supla_int_t (*_func_srpc_pack_get_caption_size)( + void *pack, _supla_int_t idx); + +void SRPC_ICACHE_FLASH srpc_getpack( + Tsrpc *srpc, TsrpcReceivedData *rd, unsigned _supla_int_t pack_sizeof, + unsigned _supla_int_t item_sizeof, unsigned _supla_int_t pack_max_count, + unsigned _supla_int_t caption_max_size, + _func_srpc_pack_get_pack_count pack_get_count, + _func_srpc_pack_set_pack_count pack_set_count, + _func_srpc_pack_get_item_ptr get_item_ptr, + _func_srpc_pack_get_item_caption_size get_item_caption_size) { + _supla_int_t header_size = pack_sizeof - (item_sizeof * pack_max_count); + _supla_int_t c_header_size = item_sizeof - caption_max_size; + _supla_int_t a, count, size, offset, pack_size; + void *pack = NULL; + + if (srpc->sdp.data_size < header_size || srpc->sdp.data_size > pack_sizeof) { + return; + } + + count = pack_get_count(srpc->sdp.data); + + if (count < 0 || count > pack_max_count) { + return; + } + + pack_size = header_size + (item_sizeof * count); + pack = (TSC_SuplaChannelPack *)malloc(pack_size); + + if (pack == NULL) return; + + memset(pack, 0, pack_size); + memcpy(pack, srpc->sdp.data, header_size); + + offset = header_size; + pack_set_count(pack, 0, 0); + + for (a = 0; a < count; a++) + if (srpc->sdp.data_size - offset >= c_header_size) { + size = get_item_caption_size(&srpc->sdp.data[offset]); + + if (size >= 0 && size <= caption_max_size && + srpc->sdp.data_size - offset >= c_header_size + size) { + memcpy(get_item_ptr(pack, a), &srpc->sdp.data[offset], + c_header_size + size); + offset += c_header_size + size; + pack_set_count(pack, 1, 1); + + } else { + break; + } + } + + if (count == pack_get_count(pack)) { + srpc->sdp.data_size = 0; + // dcs_ping is 1st variable in union + rd->data.dcs_ping = pack; + + } else { + free(pack); + } +} + +void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaChannelPack *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count(void *pack) { + return ((TSC_SuplaChannelPack *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelPack *)pack)->count = count; + } else { + ((TSC_SuplaChannelPack *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelpack_get_item_caption_size(void *item) { + return ((TSC_SuplaChannel *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelpack(Tsrpc *srpc, TsrpcReceivedData *rd) { + srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelPack), sizeof(TSC_SuplaChannel), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + &srpc_channelpack_get_pack_count, + &srpc_channelpack_set_pack_count, &srpc_channelpack_get_item_ptr, + &srpc_channelpack_get_item_caption_size); +} + +void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_b(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaChannelPack_B *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_b(void *pack) { + return ((TSC_SuplaChannelPack_B *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_b( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelPack_B *)pack)->count = count; + } else { + ((TSC_SuplaChannelPack_B *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelpack_get_item_caption_size_b(void *item) { + return ((TSC_SuplaChannel_B *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelpack_b(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack( + srpc, rd, sizeof(TSC_SuplaChannelPack_B), sizeof(TSC_SuplaChannel_B), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + &srpc_channelpack_get_pack_count_b, &srpc_channelpack_set_pack_count_b, + &srpc_channelpack_get_item_ptr_b, + &srpc_channelpack_get_item_caption_size_b); +} + +void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_c(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaChannelPack_C *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_c(void *pack) { + return ((TSC_SuplaChannelPack_C *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_c( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelPack_C *)pack)->count = count; + } else { + ((TSC_SuplaChannelPack_C *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelpack_get_item_caption_size_c(void *item) { + return ((TSC_SuplaChannel_C *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelpack_c(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack( + srpc, rd, sizeof(TSC_SuplaChannelPack_C), sizeof(TSC_SuplaChannel_C), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + &srpc_channelpack_get_pack_count_c, &srpc_channelpack_set_pack_count_c, + &srpc_channelpack_get_item_ptr_c, + &srpc_channelpack_get_item_caption_size_c); +} + +void *SRPC_ICACHE_FLASH srpc_channelpack_get_item_ptr_d(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaChannelPack_D *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_channelpack_get_pack_count_d(void *pack) { + return ((TSC_SuplaChannelPack_D *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelpack_set_pack_count_d( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelPack_D *)pack)->count = count; + } else { + ((TSC_SuplaChannelPack_D *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelpack_get_item_caption_size_d(void *item) { + return ((TSC_SuplaChannel_D *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelpack_d(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack( + srpc, rd, sizeof(TSC_SuplaChannelPack_D), sizeof(TSC_SuplaChannel_D), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + &srpc_channelpack_get_pack_count_d, &srpc_channelpack_set_pack_count_d, + &srpc_channelpack_get_item_ptr_d, + &srpc_channelpack_get_item_caption_size_d); +} + +void *SRPC_ICACHE_FLASH srpc_channelgroup_pack_get_item_ptr(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaChannelGroupPack *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_channelgroup_pack_get_pack_count(void *pack) { + return ((TSC_SuplaChannelGroupPack *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelgroup_pack_set_pack_count( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelGroupPack *)pack)->count = count; + } else { + ((TSC_SuplaChannelGroupPack *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelgroup_pack_get_item_caption_size(void *item) { + return ((TSC_SuplaChannelGroup *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelgroup_pack(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelGroupPack), + sizeof(TSC_SuplaChannelGroup), SUPLA_CHANNELGROUP_PACK_MAXCOUNT, + SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, + &srpc_channelgroup_pack_get_pack_count, + &srpc_channelgroup_pack_set_pack_count, + &srpc_channelgroup_pack_get_item_ptr, + &srpc_channelgroup_pack_get_item_caption_size); +} + +void *SRPC_ICACHE_FLASH +srpc_channelgroup_pack_b_get_item_ptr(void *pack, _supla_int_t idx) { + return &((TSC_SuplaChannelGroupPack_B *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_channelgroup_pack_b_get_pack_count(void *pack) { + return ((TSC_SuplaChannelGroupPack_B *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_channelgroup_pack_b_set_pack_count( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaChannelGroupPack_B *)pack)->count = count; + } else { + ((TSC_SuplaChannelGroupPack_B *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_channelgroup_pack_b_get_item_caption_size(void *item) { + return ((TSC_SuplaChannelGroup_B *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getchannelgroup_pack_b(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack(srpc, rd, sizeof(TSC_SuplaChannelGroupPack_B), + sizeof(TSC_SuplaChannelGroup_B), + SUPLA_CHANNELGROUP_PACK_MAXCOUNT, + SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, + &srpc_channelgroup_pack_b_get_pack_count, + &srpc_channelgroup_pack_b_set_pack_count, + &srpc_channelgroup_pack_b_get_item_ptr, + &srpc_channelgroup_pack_b_get_item_caption_size); +} + +void *SRPC_ICACHE_FLASH srpc_locationpack_get_item_ptr(void *pack, + _supla_int_t idx) { + return &((TSC_SuplaLocationPack *)pack)->items[idx]; // NOLINT +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_locationpack_get_pack_count(void *pack) { + return ((TSC_SuplaLocationPack *)pack)->count; +} + +void SRPC_ICACHE_FLASH srpc_locationpack_set_pack_count( + void *pack, _supla_int_t count, unsigned char increment) { + if (increment == 0) { + ((TSC_SuplaLocationPack *)pack)->count = count; + } else { + ((TSC_SuplaLocationPack *)pack)->count += count; + } +} + +unsigned _supla_int_t SRPC_ICACHE_FLASH +srpc_locationpack_get_item_caption_size(void *item) { + return ((TSC_SuplaLocation *)item)->CaptionSize; +} + +void SRPC_ICACHE_FLASH srpc_getlocationpack(Tsrpc *srpc, + TsrpcReceivedData *rd) { + srpc_getpack( + srpc, rd, sizeof(TSC_SuplaLocationPack), sizeof(TSC_SuplaLocation), + SUPLA_LOCATIONPACK_MAXCOUNT, SUPLA_LOCATION_CAPTION_MAXSIZE, + &srpc_locationpack_get_pack_count, &srpc_locationpack_set_pack_count, + &srpc_locationpack_get_item_ptr, + &srpc_locationpack_get_item_caption_size); +} + +char SRPC_ICACHE_FLASH srpc_getdata(void *_srpc, TsrpcReceivedData *rd, + unsigned _supla_int_t rr_id) { + Tsrpc *srpc = (Tsrpc *)_srpc; + char call_with_no_data = 0; + rd->call_type = 0; + + lck_lock(srpc->lck); + + if (SUPLA_RESULT_TRUE == srpc_in_queue_pop(srpc, &srpc->sdp, rr_id)) { + rd->call_type = srpc->sdp.call_type; + rd->rr_id = srpc->sdp.rr_id; + + // first one + rd->data.dcs_ping = NULL; + + switch (srpc->sdp.call_type) { + case SUPLA_DCS_CALL_GETVERSION: + case SUPLA_CS_CALL_GET_NEXT: + case SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED: + call_with_no_data = 1; + break; + + case SUPLA_SDC_CALL_GETVERSION_RESULT: + + if (srpc->sdp.data_size == sizeof(TSDC_SuplaGetVersionResult)) + rd->data.sdc_getversion_result = (TSDC_SuplaGetVersionResult *)malloc( + sizeof(TSDC_SuplaGetVersionResult)); + + break; + + case SUPLA_SDC_CALL_VERSIONERROR: + + if (srpc->sdp.data_size == sizeof(TSDC_SuplaVersionError)) + rd->data.sdc_version_error = + (TSDC_SuplaVersionError *)malloc(sizeof(TSDC_SuplaVersionError)); + + break; + + case SUPLA_DCS_CALL_PING_SERVER: + + if (srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer) || + srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer_COMPAT)) { + rd->data.dcs_ping = + (TDCS_SuplaPingServer *)malloc(sizeof(TDCS_SuplaPingServer)); + +#ifndef __AVR__ + if (srpc->sdp.data_size == sizeof(TDCS_SuplaPingServer_COMPAT)) { + TDCS_SuplaPingServer_COMPAT *compat = + (TDCS_SuplaPingServer_COMPAT *)srpc->sdp.data; + + rd->data.dcs_ping->now.tv_sec = compat->now.tv_sec; + rd->data.dcs_ping->now.tv_usec = compat->now.tv_usec; + call_with_no_data = 1; + } +#endif + } + break; + + case SUPLA_SDC_CALL_PING_SERVER_RESULT: + + if (srpc->sdp.data_size == sizeof(TSDC_SuplaPingServerResult)) + rd->data.sdc_ping_result = (TSDC_SuplaPingServerResult *)malloc( + sizeof(TSDC_SuplaPingServerResult)); + + break; + + case SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT: + + if (srpc->sdp.data_size == sizeof(TDCS_SuplaSetActivityTimeout)) + rd->data.dcs_set_activity_timeout = + (TDCS_SuplaSetActivityTimeout *)malloc( + sizeof(TDCS_SuplaSetActivityTimeout)); + + break; + + case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: + + if (srpc->sdp.data_size == sizeof(TSDC_SuplaSetActivityTimeoutResult)) + rd->data.sdc_set_activity_timeout_result = + (TSDC_SuplaSetActivityTimeoutResult *)malloc( + sizeof(TSDC_SuplaSetActivityTimeoutResult)); + + break; + + case SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT: + + if (srpc->sdp.data_size == sizeof(TSDC_RegistrationEnabled)) + rd->data.sdc_reg_enabled = (TSDC_RegistrationEnabled *)malloc( + sizeof(TSDC_RegistrationEnabled)); + + break; + case SUPLA_DCS_CALL_GET_USER_LOCALTIME: + call_with_no_data = 1; + break; + case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: + if (srpc->sdp.data_size <= sizeof(TSDC_UserLocalTimeResult) && + srpc->sdp.data_size >= + (sizeof(TSDC_UserLocalTimeResult) - SUPLA_TIMEZONE_MAXSIZE)) { + rd->data.sdc_user_localtime_result = + (TSDC_UserLocalTimeResult *)malloc( + sizeof(TSDC_UserLocalTimeResult)); + } + + break; + + case SUPLA_CSD_CALL_GET_CHANNEL_STATE: + if (srpc->sdp.data_size == sizeof(TCSD_ChannelStateRequest)) + rd->data.csd_channel_state_request = + (TCSD_ChannelStateRequest *)malloc( + sizeof(TCSD_ChannelStateRequest)); + break; + case SUPLA_DSC_CALL_CHANNEL_STATE_RESULT: + if (srpc->sdp.data_size == sizeof(TDSC_ChannelState)) + rd->data.dsc_channel_state = + (TDSC_ChannelState *)malloc(sizeof(TDSC_ChannelState)); + break; + +#ifndef SRPC_EXCLUDE_DEVICE + case SUPLA_DS_CALL_REGISTER_DEVICE: + + if (srpc->sdp.data_size >= + (sizeof(TDS_SuplaRegisterDevice) - + (sizeof(TDS_SuplaDeviceChannel) * SUPLA_CHANNELMAXCOUNT)) && + srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice)) { + rd->data.ds_register_device = (TDS_SuplaRegisterDevice *)malloc( + sizeof(TDS_SuplaRegisterDevice)); + } + + break; + + case SUPLA_DS_CALL_REGISTER_DEVICE_B: // ver. >= 2 + + if (srpc->sdp.data_size >= + (sizeof(TDS_SuplaRegisterDevice_B) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && + srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_B)) { + rd->data.ds_register_device_b = (TDS_SuplaRegisterDevice_B *)malloc( + sizeof(TDS_SuplaRegisterDevice_B)); + } + + break; + + case SUPLA_DS_CALL_REGISTER_DEVICE_C: // ver. >= 6 + + if (srpc->sdp.data_size >= + (sizeof(TDS_SuplaRegisterDevice_C) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && + srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_C)) { + rd->data.ds_register_device_c = (TDS_SuplaRegisterDevice_C *)malloc( + sizeof(TDS_SuplaRegisterDevice_C)); + } + + break; + + case SUPLA_DS_CALL_REGISTER_DEVICE_D: // ver. >= 7 + + if (srpc->sdp.data_size >= + (sizeof(TDS_SuplaRegisterDevice_D) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT)) && + srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_D)) { + rd->data.ds_register_device_d = (TDS_SuplaRegisterDevice_D *)malloc( + sizeof(TDS_SuplaRegisterDevice_D)); + } + + break; + + case SUPLA_DS_CALL_REGISTER_DEVICE_E: // ver. >= 10 + + if (srpc->sdp.data_size >= + (sizeof(TDS_SuplaRegisterDevice_E) - + (sizeof(TDS_SuplaDeviceChannel_C) * SUPLA_CHANNELMAXCOUNT)) && + srpc->sdp.data_size <= sizeof(TDS_SuplaRegisterDevice_E)) { + rd->data.ds_register_device_e = (TDS_SuplaRegisterDevice_E *)malloc( + sizeof(TDS_SuplaRegisterDevice_E)); + } + + break; + + case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: + + if (srpc->sdp.data_size == sizeof(TSD_SuplaRegisterDeviceResult)) + rd->data.sd_register_device_result = + (TSD_SuplaRegisterDeviceResult *)malloc( + sizeof(TSD_SuplaRegisterDeviceResult)); + break; + + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED: + + if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue)) + rd->data.ds_device_channel_value = + (TDS_SuplaDeviceChannelValue *)malloc( + sizeof(TDS_SuplaDeviceChannelValue)); + + break; + + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B: + + if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue_B)) + rd->data.ds_device_channel_value_b = + (TDS_SuplaDeviceChannelValue_B *)malloc( + sizeof(TDS_SuplaDeviceChannelValue_B)); + + break; + + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C: + + if (srpc->sdp.data_size == sizeof(TDS_SuplaDeviceChannelValue_C)) + rd->data.ds_device_channel_value_c = + (TDS_SuplaDeviceChannelValue_C *)malloc( + sizeof(TDS_SuplaDeviceChannelValue_C)); + + break; + + case SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED: + + if (srpc->sdp.data_size <= + sizeof(TDS_SuplaDeviceChannelExtendedValue) && + srpc->sdp.data_size >= + (sizeof(TDS_SuplaDeviceChannelExtendedValue) - + SUPLA_CHANNELEXTENDEDVALUE_SIZE)) + rd->data.ds_device_channel_extendedvalue = + (TDS_SuplaDeviceChannelExtendedValue *)malloc( + sizeof(TDS_SuplaDeviceChannelExtendedValue)); + + break; + + case SUPLA_SD_CALL_CHANNEL_SET_VALUE: + + if (srpc->sdp.data_size == sizeof(TSD_SuplaChannelNewValue)) + rd->data.sd_channel_new_value = (TSD_SuplaChannelNewValue *)malloc( + sizeof(TSD_SuplaChannelNewValue)); + + break; + + case SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE: + + if (srpc->sdp.data_size == sizeof(TSD_SuplaChannelGroupNewValue)) + rd->data.sd_channelgroup_new_value = + (TSD_SuplaChannelGroupNewValue *)malloc( + sizeof(TSD_SuplaChannelGroupNewValue)); + + break; + + case SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT: + + if (srpc->sdp.data_size == sizeof(TDS_SuplaChannelNewValueResult)) + rd->data.ds_channel_new_value_result = + (TDS_SuplaChannelNewValueResult *)malloc( + sizeof(TDS_SuplaChannelNewValueResult)); + + break; + + case SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL: + + if (srpc->sdp.data_size == sizeof(TDS_FirmwareUpdateParams)) + rd->data.ds_firmware_update_params = + (TDS_FirmwareUpdateParams *)malloc( + sizeof(TDS_FirmwareUpdateParams)); + + break; + + case SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT: + + if (srpc->sdp.data_size == sizeof(TSD_FirmwareUpdate_UrlResult) || + srpc->sdp.data_size == sizeof(char)) { + rd->data.sc_firmware_update_url_result = + (TSD_FirmwareUpdate_UrlResult *)malloc( + sizeof(TSD_FirmwareUpdate_UrlResult)); + + if (srpc->sdp.data_size == sizeof(char) && + rd->data.sc_firmware_update_url_result != NULL) + memset(rd->data.sc_firmware_update_url_result, 0, + sizeof(TSD_FirmwareUpdate_UrlResult)); + } + break; + case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: + if (srpc->sdp.data_size <= sizeof(TSD_DeviceCalCfgRequest) && + srpc->sdp.data_size >= + (sizeof(TSD_DeviceCalCfgRequest) - SUPLA_CALCFG_DATA_MAXSIZE)) { + rd->data.sd_device_calcfg_request = (TSD_DeviceCalCfgRequest *)malloc( + sizeof(TSD_DeviceCalCfgRequest)); + } + break; + case SUPLA_DS_CALL_DEVICE_CALCFG_RESULT: + if (srpc->sdp.data_size <= sizeof(TDS_DeviceCalCfgResult) && + srpc->sdp.data_size >= + (sizeof(TDS_DeviceCalCfgResult) - SUPLA_CALCFG_DATA_MAXSIZE)) { + rd->data.ds_device_calcfg_result = + (TDS_DeviceCalCfgResult *)malloc(sizeof(TDS_DeviceCalCfgResult)); + } + break; + case SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS: + call_with_no_data = 1; + break; + case SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT: + if (srpc->sdp.data_size <= sizeof(TSD_ChannelFunctions) && + srpc->sdp.data_size >= + (sizeof(TSD_ChannelFunctions) - + sizeof(_supla_int_t) * SUPLA_CHANNELMAXCOUNT)) { + rd->data.sd_channel_functions = + (TSD_ChannelFunctions *)malloc(sizeof(TSD_ChannelFunctions)); + } + break; + case SUPLA_DS_CALL_GET_CHANNEL_CONFIG: + if (srpc->sdp.data_size == sizeof(TDS_GetChannelConfigRequest)) { + rd->data.ds_get_channel_config_request = + (TDS_GetChannelConfigRequest *)malloc( + sizeof(TDS_GetChannelConfigRequest)); + } + break; + case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: + if (srpc->sdp.data_size <= sizeof(TSD_ChannelConfig) && + srpc->sdp.data_size >= + (sizeof(TSD_ChannelConfig) - SUPLA_CHANNEL_CONFIG_MAXSIZE)) { + rd->data.sd_channel_config = + (TSD_ChannelConfig *)malloc(sizeof(TSD_ChannelConfig)); + } + break; + case SUPLA_DS_CALL_ACTIONTRIGGER: + if (srpc->sdp.data_size == sizeof(TDS_ActionTrigger)) { + rd->data.ds_action_trigger = + (TDS_ActionTrigger *)malloc(sizeof(TDS_ActionTrigger)); + } + break; +#endif /*#ifndef SRPC_EXCLUDE_DEVICE*/ + +#ifndef SRPC_EXCLUDE_CLIENT + case SUPLA_CS_CALL_REGISTER_CLIENT: + + if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient)) + rd->data.cs_register_client = (TCS_SuplaRegisterClient *)malloc( + sizeof(TCS_SuplaRegisterClient)); + + break; + + case SUPLA_CS_CALL_REGISTER_CLIENT_B: // ver. >= 6 + + if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_B)) + rd->data.cs_register_client_b = (TCS_SuplaRegisterClient_B *)malloc( + sizeof(TCS_SuplaRegisterClient_B)); + + break; + + case SUPLA_CS_CALL_REGISTER_CLIENT_C: // ver. >= 7 + + if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_C)) + rd->data.cs_register_client_c = (TCS_SuplaRegisterClient_C *)malloc( + sizeof(TCS_SuplaRegisterClient_C)); + + break; + + case SUPLA_CS_CALL_REGISTER_CLIENT_D: // ver. >= 12 + + if (srpc->sdp.data_size == sizeof(TCS_SuplaRegisterClient_D)) + rd->data.cs_register_client_d = (TCS_SuplaRegisterClient_D *)malloc( + sizeof(TCS_SuplaRegisterClient_D)); + + break; + + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT: + + if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult)) + rd->data.sc_register_client_result = + (TSC_SuplaRegisterClientResult *)malloc( + sizeof(TSC_SuplaRegisterClientResult)); + + break; + + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B: + + if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult_B)) + rd->data.sc_register_client_result_b = + (TSC_SuplaRegisterClientResult_B *)malloc( + sizeof(TSC_SuplaRegisterClientResult_B)); + + break; + + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C: + + if (srpc->sdp.data_size == sizeof(TSC_SuplaRegisterClientResult_C)) + rd->data.sc_register_client_result_c = + (TSC_SuplaRegisterClientResult_C *)malloc( + sizeof(TSC_SuplaRegisterClientResult_C)); + + break; + + case SUPLA_SC_CALL_LOCATION_UPDATE: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaLocation) - SUPLA_LOCATION_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaLocation)) { + rd->data.sc_location = + (TSC_SuplaLocation *)malloc(sizeof(TSC_SuplaLocation)); + } + + break; + + case SUPLA_SC_CALL_LOCATIONPACK_UPDATE: + srpc_getlocationpack(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNEL_UPDATE: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannel) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaChannel)) { + rd->data.sc_channel = + (TSC_SuplaChannel *)malloc(sizeof(TSC_SuplaChannel)); + } + + break; + + case SUPLA_SC_CALL_CHANNEL_UPDATE_B: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannel_B) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_B)) { + rd->data.sc_channel_b = + (TSC_SuplaChannel_B *)malloc(sizeof(TSC_SuplaChannel_B)); + } + + break; + + case SUPLA_SC_CALL_CHANNEL_UPDATE_C: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannel_C) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_C)) { + rd->data.sc_channel_c = + (TSC_SuplaChannel_C *)malloc(sizeof(TSC_SuplaChannel_C)); + } + + break; + + case SUPLA_SC_CALL_CHANNEL_UPDATE_D: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannel_D) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaChannel_D)) { + rd->data.sc_channel_d = + (TSC_SuplaChannel_D *)malloc(sizeof(TSC_SuplaChannel_D)); + } + + break; + + case SUPLA_SC_CALL_CHANNELPACK_UPDATE: + srpc_getchannelpack(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_B: + srpc_getchannelpack_b(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_C: + srpc_getchannelpack_c(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_D: + srpc_getchannelpack_d(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE: + + if (srpc->sdp.data_size == sizeof(TSC_SuplaChannelValue)) + rd->data.sc_channel_value = + (TSC_SuplaChannelValue *)malloc(sizeof(TSC_SuplaChannelValue)); + + break; + + case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B: + + if (srpc->sdp.data_size == sizeof(TSC_SuplaChannelValue_B)) + rd->data.sc_channel_value_b = (TSC_SuplaChannelValue_B *)malloc( + sizeof(TSC_SuplaChannelValue_B)); + + break; + + case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE: + srpc_getchannelgroup_pack(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B: + srpc_getchannelgroup_pack_b(srpc, rd); + break; + + case SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE: + if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelGroupRelationPack) && + srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannelGroupRelationPack) - + (sizeof(TSC_SuplaChannelGroupRelation) * + SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT))) { + rd->data.sc_channelgroup_relation_pack = + (TSC_SuplaChannelGroupRelationPack *)malloc( + sizeof(TSC_SuplaChannelGroupRelationPack)); + } + break; + + case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE: + if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelValuePack) && + srpc->sdp.data_size >= (sizeof(TSC_SuplaChannelValuePack) - + (sizeof(TSC_SuplaChannelValue) * + SUPLA_CHANNELVALUE_PACK_MAXCOUNT))) { + rd->data.sc_channelvalue_pack = (TSC_SuplaChannelValuePack *)malloc( + sizeof(TSC_SuplaChannelValuePack)); + } + break; + + case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B: + if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelValuePack_B) && + srpc->sdp.data_size >= (sizeof(TSC_SuplaChannelValuePack_B) - + (sizeof(TSC_SuplaChannelValue_B) * + SUPLA_CHANNELVALUE_PACK_MAXCOUNT))) { + rd->data.sc_channelvalue_pack_b = + (TSC_SuplaChannelValuePack_B *)malloc( + sizeof(TSC_SuplaChannelValuePack_B)); + } + break; + + case SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE: + if (srpc->sdp.data_size <= sizeof(TSC_SuplaChannelExtendedValuePack) && + srpc->sdp.data_size >= + (sizeof(TSC_SuplaChannelExtendedValuePack) - + SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE)) { + rd->data.sc_channelextendedvalue_pack = + (TSC_SuplaChannelExtendedValuePack *)malloc( + sizeof(TSC_SuplaChannelExtendedValuePack)); + } + break; + + case SUPLA_CS_CALL_CHANNEL_SET_VALUE: + + if (srpc->sdp.data_size == sizeof(TCS_SuplaChannelNewValue)) + rd->data.cs_channel_new_value = (TCS_SuplaChannelNewValue *)malloc( + sizeof(TCS_SuplaChannelNewValue)); + + break; + + case SUPLA_CS_CALL_SET_VALUE: + + if (srpc->sdp.data_size == sizeof(TCS_SuplaNewValue)) + rd->data.cs_new_value = + (TCS_SuplaNewValue *)malloc(sizeof(TCS_SuplaNewValue)); + + break; + + case SUPLA_CS_CALL_CHANNEL_SET_VALUE_B: + + if (srpc->sdp.data_size == sizeof(TCS_SuplaChannelNewValue_B)) + rd->data.cs_channel_new_value_b = + (TCS_SuplaChannelNewValue_B *)malloc( + sizeof(TCS_SuplaChannelNewValue_B)); + + break; + + case SUPLA_SC_CALL_EVENT: + + if (srpc->sdp.data_size >= + (sizeof(TSC_SuplaEvent) - SUPLA_SENDER_NAME_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SuplaEvent)) { + rd->data.sc_event = (TSC_SuplaEvent *)malloc(sizeof(TSC_SuplaEvent)); + } + + break; + + case SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST: + call_with_no_data = 1; + break; + + case SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT: + if (srpc->sdp.data_size >= (sizeof(TSC_OAuthTokenRequestResult) - + SUPLA_OAUTH_TOKEN_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_OAuthTokenRequestResult)) { + rd->data.sc_oauth_tokenrequest_result = + (TSC_OAuthTokenRequestResult *)malloc( + sizeof(TSC_OAuthTokenRequestResult)); + } + break; + case SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST: + if (srpc->sdp.data_size == sizeof(TCS_SuperUserAuthorizationRequest)) + rd->data.cs_superuser_authorization_request = + (TCS_SuperUserAuthorizationRequest *)malloc( + sizeof(TCS_SuperUserAuthorizationRequest)); + break; + case SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT: + call_with_no_data = 1; + break; + case SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT: + if (srpc->sdp.data_size == sizeof(TSC_SuperUserAuthorizationResult)) + rd->data.sc_superuser_authorization_result = + (TSC_SuperUserAuthorizationResult *)malloc( + sizeof(TSC_SuperUserAuthorizationResult)); + break; + case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST: + if (srpc->sdp.data_size <= sizeof(TCS_DeviceCalCfgRequest) && + srpc->sdp.data_size >= + (sizeof(TCS_DeviceCalCfgRequest) - SUPLA_CALCFG_DATA_MAXSIZE)) { + rd->data.cs_device_calcfg_request = (TCS_DeviceCalCfgRequest *)malloc( + sizeof(TCS_DeviceCalCfgRequest)); + } + break; + case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B: + if (srpc->sdp.data_size <= sizeof(TCS_DeviceCalCfgRequest_B) && + srpc->sdp.data_size >= (sizeof(TCS_DeviceCalCfgRequest_B) - + SUPLA_CALCFG_DATA_MAXSIZE)) { + rd->data.cs_device_calcfg_request_b = + (TCS_DeviceCalCfgRequest_B *)malloc( + sizeof(TCS_DeviceCalCfgRequest_B)); + } + break; + case SUPLA_SC_CALL_DEVICE_CALCFG_RESULT: + if (srpc->sdp.data_size <= sizeof(TSC_DeviceCalCfgResult) && + srpc->sdp.data_size >= + (sizeof(TSC_DeviceCalCfgResult) - SUPLA_CALCFG_DATA_MAXSIZE)) { + rd->data.sc_device_calcfg_result = + (TSC_DeviceCalCfgResult *)malloc(sizeof(TSC_DeviceCalCfgResult)); + } + break; + + case SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG: + if (srpc->sdp.data_size == sizeof(TCS_ChannelBasicCfgRequest)) + rd->data.cs_channel_basic_cfg_request = + (TCS_ChannelBasicCfgRequest *)malloc( + sizeof(TCS_ChannelBasicCfgRequest)); + break; + case SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT: + if (srpc->sdp.data_size >= + (sizeof(TSC_ChannelBasicCfg) - SUPLA_CHANNEL_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_ChannelBasicCfg)) + rd->data.sc_channel_basic_cfg = + (TSC_ChannelBasicCfg *)malloc(sizeof(TSC_ChannelBasicCfg)); + break; + + case SUPLA_CS_CALL_SET_CHANNEL_FUNCTION: + if (srpc->sdp.data_size == sizeof(TCS_SetChannelFunction)) + rd->data.cs_set_channel_function = + (TCS_SetChannelFunction *)malloc(sizeof(TCS_SetChannelFunction)); + break; + + case SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT: + if (srpc->sdp.data_size == sizeof(TSC_SetChannelFunctionResult)) + rd->data.sc_set_channel_function_result = + (TSC_SetChannelFunctionResult *)malloc( + sizeof(TSC_SetChannelFunctionResult)); + break; + + case SUPLA_CS_CALL_SET_CHANNEL_CAPTION: + case SUPLA_CS_CALL_SET_LOCATION_CAPTION: + if (srpc->sdp.data_size >= + (sizeof(TCS_SetCaption) - SUPLA_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TCS_SetCaption)) + rd->data.cs_set_caption = + (TCS_SetCaption *)malloc(sizeof(TCS_SetCaption)); + break; + + case SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT: + case SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT: + if (srpc->sdp.data_size >= + (sizeof(TSC_SetCaptionResult) - SUPLA_CAPTION_MAXSIZE) && + srpc->sdp.data_size <= sizeof(TSC_SetCaptionResult)) + rd->data.sc_set_caption_result = + (TSC_SetCaptionResult *)malloc(sizeof(TSC_SetCaptionResult)); + break; + + case SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST: + call_with_no_data = 1; + break; + + case SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT: + if (srpc->sdp.data_size == sizeof(TSC_ClientsReconnectRequestResult)) + rd->data.sc_clients_reconnect_result = + (TSC_ClientsReconnectRequestResult *)malloc( + sizeof(TSC_ClientsReconnectRequestResult)); + break; + + case SUPLA_CS_CALL_SET_REGISTRATION_ENABLED: + if (srpc->sdp.data_size == sizeof(TCS_SetRegistrationEnabled)) + rd->data.cs_set_registration_enabled = + (TCS_SetRegistrationEnabled *)malloc( + sizeof(TCS_SetRegistrationEnabled)); + break; + + case SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT: + if (srpc->sdp.data_size == sizeof(TSC_SetRegistrationEnabledResult)) + rd->data.sc_set_registration_enabled_result = + (TSC_SetRegistrationEnabledResult *)malloc( + sizeof(TSC_SetRegistrationEnabledResult)); + break; + + case SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST: + if (srpc->sdp.data_size == sizeof(TCS_DeviceReconnectRequest)) + rd->data.cs_device_reconnect_request = + (TCS_DeviceReconnectRequest *)malloc( + sizeof(TCS_DeviceReconnectRequest)); + break; + case SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT: + if (srpc->sdp.data_size == sizeof(TSC_DeviceReconnectRequestResult)) + rd->data.sc_device_reconnect_request_result = + (TSC_DeviceReconnectRequestResult *)malloc( + sizeof(TSC_DeviceReconnectRequestResult)); + break; + + case SUPLA_CS_CALL_TIMER_ARM: + if (srpc->sdp.data_size == sizeof(TCS_TimerArmRequest)) + rd->data.cs_timer_arm_request = + (TCS_TimerArmRequest *)malloc(sizeof(TCS_TimerArmRequest)); + break; + +#endif /*#ifndef SRPC_EXCLUDE_CLIENT*/ + } + + if (call_with_no_data == 1) { + return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); + } + + if (rd->data.dcs_ping != NULL) { + if (srpc->sdp.data_size > 0) { + memcpy(rd->data.dcs_ping, srpc->sdp.data, srpc->sdp.data_size); + } + + return lck_unlock_r(srpc->lck, SUPLA_RESULT_TRUE); + } + + return lck_unlock_r(srpc->lck, SUPLA_RESULT_DATA_ERROR); + } + + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); +} + +void SRPC_ICACHE_FLASH srpc_rd_free(TsrpcReceivedData *rd) { + if (rd->call_type > 0) { + // first one + + if (rd->data.dcs_ping != NULL) free(rd->data.dcs_ping); + + rd->call_type = 0; + } +} + +unsigned char SRPC_ICACHE_FLASH +srpc_call_min_version_required(void *_srpc, unsigned _supla_int_t call_type) { + switch (call_type) { + case SUPLA_DCS_CALL_GETVERSION: + case SUPLA_SDC_CALL_GETVERSION_RESULT: + case SUPLA_SDC_CALL_VERSIONERROR: + case SUPLA_DCS_CALL_PING_SERVER: + case SUPLA_SDC_CALL_PING_SERVER_RESULT: + case SUPLA_DS_CALL_REGISTER_DEVICE: + case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: + case SUPLA_CS_CALL_REGISTER_CLIENT: + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT: + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED: + case SUPLA_SD_CALL_CHANNEL_SET_VALUE: + case SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT: + case SUPLA_SC_CALL_LOCATION_UPDATE: + case SUPLA_SC_CALL_LOCATIONPACK_UPDATE: + case SUPLA_SC_CALL_CHANNEL_UPDATE: + case SUPLA_SC_CALL_CHANNELPACK_UPDATE: + case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE: + case SUPLA_CS_CALL_GET_NEXT: + case SUPLA_SC_CALL_EVENT: + case SUPLA_CS_CALL_CHANNEL_SET_VALUE: + return 1; + + case SUPLA_DS_CALL_REGISTER_DEVICE_B: + case SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT: + case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: + return 2; + + case SUPLA_CS_CALL_CHANNEL_SET_VALUE_B: + return 3; + + case SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL: + case SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT: + return 5; + + case SUPLA_DS_CALL_REGISTER_DEVICE_C: + case SUPLA_CS_CALL_REGISTER_CLIENT_B: + return 6; + + case SUPLA_CS_CALL_REGISTER_CLIENT_C: + case SUPLA_DS_CALL_REGISTER_DEVICE_D: + case SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED: + case SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT: + return 7; + + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_B: + case SUPLA_SC_CALL_CHANNEL_UPDATE_B: + return 8; + + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B: + case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE: + case SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE: + case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE: + case SUPLA_CS_CALL_SET_VALUE: + return 9; + + case SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED: + case SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE: + case SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST: + case SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT: + case SUPLA_DS_CALL_REGISTER_DEVICE_E: + case SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST: + case SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT: + case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST: + case SUPLA_SC_CALL_DEVICE_CALCFG_RESULT: + case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: + case SUPLA_DS_CALL_DEVICE_CALCFG_RESULT: + case SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B: + case SUPLA_SC_CALL_CHANNEL_UPDATE_C: + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_C: + return 10; + case SUPLA_DCS_CALL_GET_USER_LOCALTIME: + case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: + case SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B: + return 11; + case SUPLA_CS_CALL_REGISTER_CLIENT_D: + case SUPLA_CSD_CALL_GET_CHANNEL_STATE: + case SUPLA_DSC_CALL_CHANNEL_STATE_RESULT: + case SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG: + case SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT: + case SUPLA_CS_CALL_SET_CHANNEL_FUNCTION: + case SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT: + case SUPLA_CS_CALL_SET_CHANNEL_CAPTION: + case SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT: + case SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST: + case SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT: + case SUPLA_CS_CALL_SET_REGISTRATION_ENABLED: + case SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT: + case SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST: + case SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT: + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B: + case SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C: + case SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS: + case SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT: + case SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT: + return 12; + case SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE: + return 13; + case SUPLA_CS_CALL_SET_LOCATION_CAPTION: + case SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT: + return 14; + case SUPLA_SC_CALL_CHANNEL_UPDATE_D: + case SUPLA_SC_CALL_CHANNELPACK_UPDATE_D: + case SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B: + case SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B: + return 15; + case SUPLA_DS_CALL_GET_CHANNEL_CONFIG: + case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: + case SUPLA_DS_CALL_ACTIONTRIGGER: + return 16; + case SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C: + case SUPLA_CS_CALL_TIMER_ARM: + return 17; + } + + return 255; +} + +unsigned char SRPC_ICACHE_FLASH +srpc_call_allowed(void *_srpc, unsigned _supla_int_t call_type) { + unsigned char min_ver = srpc_call_min_version_required(_srpc, call_type); + + if (min_ver == 0 || srpc_get_proto_version(_srpc) >= min_ver) { + return 1; + } + + return 0; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_async__call(void *_srpc, + unsigned _supla_int_t call_type, + char *data, + unsigned _supla_int_t data_size, + unsigned char *version) { + Tsrpc *srpc = (Tsrpc *)_srpc; + + if (!srpc_call_allowed(_srpc, call_type)) { + if (srpc->params.on_min_version_required != NULL) { + srpc->params.on_min_version_required( + _srpc, call_type, srpc_call_min_version_required(_srpc, call_type), + srpc->params.user_params); + } + + return SUPLA_RESULT_FALSE; + } + + if (srpc->params.before_async_call != NULL) { + srpc->params.before_async_call(_srpc, call_type, srpc->params.user_params); + } + + lck_lock(srpc->lck); + + sproto_sdp_init(srpc->proto, &srpc->sdp); + + if (version != NULL) srpc->sdp.version = *version; + + if (SUPLA_RESULT_TRUE == + sproto_set_data(&srpc->sdp, data, data_size, call_type) && + srpc_out_queue_push(srpc, &srpc->sdp)) { +#ifndef __EH_DISABLED + if (srpc->params.eh != 0) { + eh_raise_event(srpc->params.eh); + } +#endif + + return lck_unlock_r(srpc->lck, srpc->sdp.rr_id); + } + + return lck_unlock_r(srpc->lck, SUPLA_RESULT_FALSE); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_async_call(void *_srpc, unsigned _supla_int_t call_type, char *data, + unsigned _supla_int_t data_size) { + return srpc_async__call(_srpc, call_type, data, data_size, NULL); +} + +unsigned char SRPC_ICACHE_FLASH srpc_get_proto_version(void *_srpc) { + unsigned char version; + + Tsrpc *srpc = (Tsrpc *)_srpc; + lck_lock(srpc->lck); + version = sproto_get_version(srpc->proto); + lck_unlock(srpc->lck); + + return version; +} + +void SRPC_ICACHE_FLASH srpc_set_proto_version(void *_srpc, + unsigned char version) { + Tsrpc *srpc = (Tsrpc *)_srpc; + + lck_lock(srpc->lck); + sproto_set_version(srpc->proto, version); + lck_unlock(srpc->lck); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_getversion(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_DCS_CALL_GETVERSION, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_getversion_result( + void *_srpc, char SoftVer[SUPLA_SOFTVER_MAXSIZE]) { + TSDC_SuplaGetVersionResult gvr; + + gvr.proto_version = SUPLA_PROTO_VERSION; + gvr.proto_version_min = SUPLA_PROTO_VERSION_MIN; + + memcpy(gvr.SoftVer, SoftVer, SUPLA_SOFTVER_MAXSIZE); + + return srpc_async_call(_srpc, SUPLA_SDC_CALL_GETVERSION_RESULT, (char *)&gvr, + sizeof(TSDC_SuplaGetVersionResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sdc_async_versionerror(void *_srpc, unsigned char remote_version) { + TSDC_SuplaVersionError ve; + ve.server_version = SUPLA_PROTO_VERSION; + ve.server_version_min = SUPLA_PROTO_VERSION_MIN; + + return srpc_async__call(_srpc, SUPLA_SDC_CALL_VERSIONERROR, (char *)&ve, + sizeof(TSDC_SuplaVersionError), &remote_version); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_ping_server(void *_srpc) { + TDCS_SuplaPingServer ps; + +#if defined(ESP8266) + unsigned int time = system_get_time(); + ps.now.tv_sec = time / 1000000; + ps.now.tv_usec = time % 1000000; +#elif defined(__AVR__) + ps.now.tv_sec[0] = 0; + ps.now.tv_sec[1] = 0; + ps.now.tv_usec[0] = 0; + ps.now.tv_usec[1] = 0; +#else + struct timeval now; + gettimeofday(&now, NULL); + ps.now.tv_sec = now.tv_sec; + ps.now.tv_usec = now.tv_usec; +#endif + + return srpc_async_call(_srpc, SUPLA_DCS_CALL_PING_SERVER, (char *)&ps, + sizeof(TDCS_SuplaPingServer)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_ping_server_result(void *_srpc) { +#if !defined(ESP8266) && !defined(__AVR__) && !defined(ESP32) + TSDC_SuplaPingServerResult ps; + + struct timeval now; + gettimeofday(&now, NULL); + ps.now.tv_sec = now.tv_sec; + ps.now.tv_usec = now.tv_usec; + + return srpc_async_call(_srpc, SUPLA_SDC_CALL_PING_SERVER_RESULT, (char *)&ps, + sizeof(TSDC_SuplaPingServerResult)); +#else + return 0; +#endif +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout( + void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout) { + return srpc_async_call(_srpc, SUPLA_DCS_CALL_SET_ACTIVITY_TIMEOUT, + (char *)dcs_set_activity_timeout, + sizeof(TDCS_SuplaSetActivityTimeout)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout_result( + void *_srpc, + TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result) { + return srpc_async_call(_srpc, SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT, + (char *)sdc_set_activity_timeout_result, + sizeof(TSDC_SuplaSetActivityTimeoutResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_dcs_async_get_registration_enabled(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_REGISTRATION_ENABLED, NULL, + 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_registration_enabled_result( + void *_srpc, TSDC_RegistrationEnabled *reg_enabled) { + return srpc_async_call(_srpc, SUPLA_SDC_CALL_GET_REGISTRATION_ENABLED_RESULT, + (char *)reg_enabled, sizeof(TSDC_RegistrationEnabled)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_get_user_localtime(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_USER_LOCALTIME, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_user_localtime_result( + void *_srpc, TSDC_UserLocalTimeResult *localtime) { + if (localtime == NULL || localtime->timezoneSize > SUPLA_TIMEZONE_MAXSIZE) { + return 0; + } + + unsigned int size = sizeof(TSDC_UserLocalTimeResult) - + SUPLA_TIMEZONE_MAXSIZE + localtime->timezoneSize; + + return srpc_async_call(_srpc, SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT, + (char *)localtime, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_csd_async_get_channel_state( + void *_srpc, TCSD_ChannelStateRequest *request) { + return srpc_async_call(_srpc, SUPLA_CSD_CALL_GET_CHANNEL_STATE, + (char *)request, sizeof(TCSD_ChannelStateRequest)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state) { + return srpc_async_call(_srpc, SUPLA_DSC_CALL_CHANNEL_STATE_RESULT, + (char *)state, sizeof(TDSC_ChannelState)); +} + +#ifndef SRPC_EXCLUDE_DEVICE +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url( + void *_srpc, TDS_FirmwareUpdateParams *params) { + return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_FIRMWARE_UPDATE_URL, + (char *)params, sizeof(TDS_FirmwareUpdateParams)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice( + void *_srpc, TDS_SuplaRegisterDevice *registerdevice) { + _supla_int_t size = + sizeof(TDS_SuplaRegisterDevice) - + (sizeof(TDS_SuplaDeviceChannel) * SUPLA_CHANNELMAXCOUNT) + + (sizeof(TDS_SuplaDeviceChannel) * registerdevice->channel_count); + + if (size > sizeof(TDS_SuplaRegisterDevice)) return 0; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE, + (char *)registerdevice, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_b( + void *_srpc, TDS_SuplaRegisterDevice_B *registerdevice) { + _supla_int_t size = + sizeof(TDS_SuplaRegisterDevice_B) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + + (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); + + if (size > sizeof(TDS_SuplaRegisterDevice_B)) return 0; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_B, + (char *)registerdevice, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_c( + void *_srpc, TDS_SuplaRegisterDevice_C *registerdevice) { + _supla_int_t size = + sizeof(TDS_SuplaRegisterDevice_C) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + + (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); + + if (size > sizeof(TDS_SuplaRegisterDevice_C)) return 0; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_C, + (char *)registerdevice, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_d( + void *_srpc, TDS_SuplaRegisterDevice_D *registerdevice) { + _supla_int_t size = + sizeof(TDS_SuplaRegisterDevice_D) - + (sizeof(TDS_SuplaDeviceChannel_B) * SUPLA_CHANNELMAXCOUNT) + + (sizeof(TDS_SuplaDeviceChannel_B) * registerdevice->channel_count); + + if (size > sizeof(TDS_SuplaRegisterDevice_D)) return 0; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_D, + (char *)registerdevice, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_e( + void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice) { + _supla_int_t size = + sizeof(TDS_SuplaRegisterDevice_E) - + (sizeof(TDS_SuplaDeviceChannel_C) * SUPLA_CHANNELMAXCOUNT) + + (sizeof(TDS_SuplaDeviceChannel_C) * registerdevice->channel_count); + + if (size > sizeof(TDS_SuplaRegisterDevice_E)) return 0; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_REGISTER_DEVICE_E, + (char *)registerdevice, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_registerdevice_result( + void *_srpc, TSD_SuplaRegisterDeviceResult *registerdevice_result) { + return srpc_async_call(_srpc, SUPLA_SD_CALL_REGISTER_DEVICE_RESULT, + (char *)registerdevice_result, + sizeof(TSD_SuplaRegisterDeviceResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sd_async_set_channel_value(void *_srpc, TSD_SuplaChannelNewValue *value) { + return srpc_async_call(_srpc, SUPLA_SD_CALL_CHANNEL_SET_VALUE, (char *)value, + sizeof(TSD_SuplaChannelNewValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_set_channelgroup_value( + void *_srpc, TSD_SuplaChannelGroupNewValue *value) { + return srpc_async_call(_srpc, SUPLA_SD_CALL_CHANNELGROUP_SET_VALUE, + (char *)value, sizeof(TSD_SuplaChannelGroupNewValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, + _supla_int_t SenderID, char Success) { + TDS_SuplaChannelNewValueResult result; + result.ChannelNumber = ChannelNumber; + result.SenderID = SenderID; + result.Success = Success; + + return srpc_async_call(_srpc, SUPLA_DS_CALL_CHANNEL_SET_VALUE_RESULT, + (char *)&result, + sizeof(TDS_SuplaChannelNewValueResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url_result( + void *_srpc, TSD_FirmwareUpdate_UrlResult *result) { + return srpc_async_call( + _srpc, SUPLA_SD_CALL_GET_FIRMWARE_UPDATE_URL_RESULT, (char *)result, + result->exists == 1 ? sizeof(TSD_FirmwareUpdate_UrlResult) + : sizeof(char)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed( + void *_srpc, unsigned char channel_number, char *value) { + TDS_SuplaDeviceChannelValue ncsc; + ncsc.ChannelNumber = channel_number; + memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); + + return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED, + (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_channel_value_changed_b(void *_srpc, unsigned char channel_number, + char *value, unsigned char offline) { + TDS_SuplaDeviceChannelValue_B ncsc; + ncsc.ChannelNumber = channel_number; + ncsc.Offline = !!offline; + memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); + + return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_B, + (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue_B)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed_c( + void *_srpc, unsigned char channel_number, char *value, + unsigned char offline, unsigned _supla_int_t validity_time_sec) { + TDS_SuplaDeviceChannelValue_C ncsc; + ncsc.ChannelNumber = channel_number; + ncsc.Offline = !!offline; + ncsc.ValidityTimeSec = validity_time_sec; + memcpy(ncsc.value, value, SUPLA_CHANNELVALUE_SIZE); + + return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_VALUE_CHANGED_C, + (char *)&ncsc, sizeof(TDS_SuplaDeviceChannelValue_C)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_extendedvalue_changed( + void *_srpc, unsigned char channel_number, + TSuplaChannelExtendedValue *value) { + if (value == NULL || value->size > SUPLA_CHANNELEXTENDEDVALUE_SIZE || + value->size == 0) { + return 0; + } + + TDS_SuplaDeviceChannelExtendedValue ncsc; + ncsc.ChannelNumber = channel_number; + memcpy(&ncsc.value, value, sizeof(TSuplaChannelExtendedValue)); + + return srpc_async_call( + _srpc, SUPLA_DS_CALL_DEVICE_CHANNEL_EXTENDEDVALUE_CHANGED, (char *)&ncsc, + sizeof(TDS_SuplaDeviceChannelExtendedValue) - + (SUPLA_CHANNELEXTENDEDVALUE_SIZE - ncsc.value.size)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_device_calcfg_request( + void *_srpc, TSD_DeviceCalCfgRequest *request) { + if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST, + (char *)request, + sizeof(TSD_DeviceCalCfgRequest) - + SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_device_calcfg_result( + void *_srpc, TDS_DeviceCalCfgResult *result) { + if (result == NULL || result->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_DS_CALL_DEVICE_CALCFG_RESULT, + (char *)result, + sizeof(TDS_DeviceCalCfgResult) - + SUPLA_CALCFG_DATA_MAXSIZE + result->DataSize); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_get_channel_functions(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_CHANNEL_FUNCTIONS, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_functions_result( + void *_srpc, TSD_ChannelFunctions *result) { + if (result == NULL || result->ChannelCount > SUPLA_CHANNELMAXCOUNT) { + return 0; + } + + _supla_int_t size = sizeof(TSD_ChannelFunctions) - + sizeof(_supla_int_t) * SUPLA_CHANNELMAXCOUNT + + sizeof(_supla_int_t) * result->ChannelCount; + + if (size > sizeof(TSD_ChannelFunctions)) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_SD_CALL_GET_CHANNEL_FUNCTIONS_RESULT, + (char *)result, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_config( + void *_srpc, TDS_GetChannelConfigRequest *request) { + if (request == NULL) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_DS_CALL_GET_CHANNEL_CONFIG, + (char *)request, sizeof(TDS_GetChannelConfigRequest)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_config_result( + void *_srpc, TSD_ChannelConfig *config) { + if (config == NULL || config->ConfigSize > SUPLA_CHANNEL_CONFIG_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT, + (char *)config, + sizeof(TSD_ChannelConfig) - + SUPLA_CHANNEL_CONFIG_MAXSIZE + config->ConfigSize); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_action_trigger(void *_srpc, TDS_ActionTrigger *action_trigger) { + if (action_trigger == NULL) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_DS_CALL_ACTIONTRIGGER, + (char *)action_trigger, sizeof(TDS_ActionTrigger)); +} + +#endif /*SRPC_EXCLUDE_DEVICE*/ + +#ifndef SRPC_EXCLUDE_CLIENT +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient( + void *_srpc, TCS_SuplaRegisterClient *registerclient) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT, + (char *)registerclient, + sizeof(TCS_SuplaRegisterClient)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_b( + void *_srpc, TCS_SuplaRegisterClient_B *registerclient) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_B, + (char *)registerclient, + sizeof(TCS_SuplaRegisterClient_B)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_c( + void *_srpc, TCS_SuplaRegisterClient_C *registerclient) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_C, + (char *)registerclient, + sizeof(TCS_SuplaRegisterClient_C)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_d( + void *_srpc, TCS_SuplaRegisterClient_D *registerclient) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_REGISTER_CLIENT_D, + (char *)registerclient, + sizeof(TCS_SuplaRegisterClient_D)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result( + void *_srpc, TSC_SuplaRegisterClientResult *registerclient_result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT, + (char *)registerclient_result, + sizeof(TSC_SuplaRegisterClientResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_b( + void *_srpc, TSC_SuplaRegisterClientResult_B *registerclient_result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_B, + (char *)registerclient_result, + sizeof(TSC_SuplaRegisterClientResult_B)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_c( + void *_srpc, TSC_SuplaRegisterClientResult_C *registerclient_result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_REGISTER_CLIENT_RESULT_C, + (char *)registerclient_result, + sizeof(TSC_SuplaRegisterClientResult_C)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_location_update(void *_srpc, TSC_SuplaLocation *location) { + _supla_int_t size = sizeof(TSC_SuplaLocation) - + SUPLA_LOCATION_CAPTION_MAXSIZE + location->CaptionSize; + + if (size > sizeof(TSC_SuplaLocation)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_LOCATION_UPDATE, (char *)location, + size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_set_pack( + void *_srpc, void *pack, _supla_int_t count, + _func_srpc_pack_get_caption_size get_caption_size, + _func_srpc_pack_get_item_ptr get_item_ptr, + _func_srpc_pack_set_pack_count set_pack_count, + unsigned _supla_int_t pack_sizeof, unsigned _supla_int_t pack_max_count, + unsigned _supla_int_t caption_max_size, unsigned _supla_int_t item_sizeof, + unsigned _supla_int_t call_type) { + _supla_int_t result = 0; + _supla_int_t a; + _supla_int_t n = 0; + _supla_int_t size = 0; + _supla_int_t offset = 0; + + if (count < 1 || count > pack_max_count) return 0; + + size = pack_sizeof - (item_sizeof * pack_max_count); + offset = size; + + char *buffer = malloc(size); + + if (buffer == NULL) return 0; + + memcpy(buffer, pack, size); + + for (a = 0; a < count; a++) { + if (get_caption_size(pack, a) <= caption_max_size) { + size += item_sizeof - caption_max_size + get_caption_size(pack, a); + + char *new_buffer = (char *)realloc(buffer, size); + + if (new_buffer == NULL) { + free(buffer); + return 0; + } + + buffer = new_buffer; + memcpy(&buffer[offset], get_item_ptr(pack, a), size - offset); + offset += size - offset; + n++; + } + } + + set_pack_count(buffer, n, 0); + + result = srpc_async_call(_srpc, call_type, buffer, size); + + free(buffer); + return result; +} + +unsigned _supla_int_t srpc_locationpack_get_caption_size(void *pack, + _supla_int_t idx) { + return ((TSC_SuplaLocationPack *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_locationpack_update( + void *_srpc, TSC_SuplaLocationPack *location_pack) { + return srpc_set_pack( + _srpc, location_pack, location_pack->count, + &srpc_locationpack_get_caption_size, &srpc_locationpack_get_item_ptr, + &srpc_locationpack_set_pack_count, sizeof(TSC_SuplaLocationPack), + SUPLA_LOCATIONPACK_MAXCOUNT, SUPLA_LOCATION_CAPTION_MAXSIZE, + sizeof(TSC_SuplaLocation), SUPLA_SC_CALL_LOCATIONPACK_UPDATE); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_channel_update(void *_srpc, TSC_SuplaChannel *channel) { + _supla_int_t size = sizeof(TSC_SuplaChannel) - SUPLA_CHANNEL_CAPTION_MAXSIZE + + channel->CaptionSize; + + if (size > sizeof(TSC_SuplaChannel)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE, (char *)channel, + size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_channel_update_b(void *_srpc, TSC_SuplaChannel_B *channel_b) { + _supla_int_t size = sizeof(TSC_SuplaChannel_B) - + SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_b->CaptionSize; + + if (size > sizeof(TSC_SuplaChannel_B)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_B, + (char *)channel_b, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_channel_update_c(void *_srpc, TSC_SuplaChannel_C *channel_c) { + _supla_int_t size = sizeof(TSC_SuplaChannel_C) - + SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_c->CaptionSize; + + if (size > sizeof(TSC_SuplaChannel_C)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_C, + (char *)channel_c, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_channel_update_d(void *_srpc, TSC_SuplaChannel_D *channel_d) { + _supla_int_t size = sizeof(TSC_SuplaChannel_D) - + SUPLA_CHANNEL_CAPTION_MAXSIZE + channel_d->CaptionSize; + + if (size > sizeof(TSC_SuplaChannel_D)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_UPDATE_D, + (char *)channel_d, size); +} + +unsigned _supla_int_t srpc_channelpack_get_caption_size(void *pack, + _supla_int_t idx) { + return ((TSC_SuplaChannelPack *)pack)->items[idx].CaptionSize; +} + +unsigned _supla_int_t srpc_channelpack_get_caption_size_b(void *pack, + _supla_int_t idx) { + return ((TSC_SuplaChannelPack_B *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update( + void *_srpc, TSC_SuplaChannelPack *channel_pack) { + return srpc_set_pack( + _srpc, channel_pack, channel_pack->count, + &srpc_channelpack_get_caption_size, &srpc_channelpack_get_item_ptr, + &srpc_channelpack_set_pack_count, sizeof(TSC_SuplaChannelPack), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + sizeof(TSC_SuplaChannel), SUPLA_SC_CALL_CHANNELPACK_UPDATE); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_b( + void *_srpc, TSC_SuplaChannelPack_B *channel_pack) { + return srpc_set_pack( + _srpc, channel_pack, channel_pack->count, + &srpc_channelpack_get_caption_size_b, &srpc_channelpack_get_item_ptr_b, + &srpc_channelpack_set_pack_count_b, sizeof(TSC_SuplaChannelPack_B), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + sizeof(TSC_SuplaChannel_B), SUPLA_SC_CALL_CHANNELPACK_UPDATE_B); +} + +unsigned _supla_int_t srpc_channelpack_get_caption_size_c(void *pack, + _supla_int_t idx) { + return ((TSC_SuplaChannelPack_C *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_c( + void *_srpc, TSC_SuplaChannelPack_C *channel_pack) { + return srpc_set_pack( + _srpc, channel_pack, channel_pack->count, + &srpc_channelpack_get_caption_size_c, &srpc_channelpack_get_item_ptr_c, + &srpc_channelpack_set_pack_count_c, sizeof(TSC_SuplaChannelPack_C), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + sizeof(TSC_SuplaChannel_C), SUPLA_SC_CALL_CHANNELPACK_UPDATE_C); +} + +unsigned _supla_int_t srpc_channelpack_get_caption_size_d(void *pack, + _supla_int_t idx) { + return ((TSC_SuplaChannelPack_D *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_d( + void *_srpc, TSC_SuplaChannelPack_D *channel_pack) { + return srpc_set_pack( + _srpc, channel_pack, channel_pack->count, + &srpc_channelpack_get_caption_size_d, &srpc_channelpack_get_item_ptr_d, + &srpc_channelpack_set_pack_count_d, sizeof(TSC_SuplaChannelPack_D), + SUPLA_CHANNELPACK_MAXCOUNT, SUPLA_CHANNEL_CAPTION_MAXSIZE, + sizeof(TSC_SuplaChannel_D), SUPLA_SC_CALL_CHANNELPACK_UPDATE_D); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update( + void *_srpc, TSC_SuplaChannelValue *channel_value) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE, + (char *)channel_value, sizeof(TSC_SuplaChannelValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update_b( + void *_srpc, TSC_SuplaChannelValue_B *channel_value) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_VALUE_UPDATE_B, + (char *)channel_value, + sizeof(TSC_SuplaChannelValue_B)); +} + +unsigned _supla_int_t +srpc_channelgroup_pack_get_caption_size(void *pack, _supla_int_t idx) { + return ((TSC_SuplaChannelGroupPack *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update( + void *_srpc, TSC_SuplaChannelGroupPack *channelgroup_pack) { + return srpc_set_pack( + _srpc, channelgroup_pack, channelgroup_pack->count, + &srpc_channelgroup_pack_get_caption_size, + &srpc_channelgroup_pack_get_item_ptr, + &srpc_channelgroup_pack_set_pack_count, sizeof(TSC_SuplaChannelGroupPack), + SUPLA_CHANNELGROUP_PACK_MAXCOUNT, SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, + sizeof(TSC_SuplaChannelGroup), SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE); +} + +unsigned _supla_int_t +srpc_channelgroup_pack_b_get_caption_size(void *pack, _supla_int_t idx) { + return ((TSC_SuplaChannelGroupPack_B *)pack)->items[idx].CaptionSize; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update_b( + void *_srpc, TSC_SuplaChannelGroupPack_B *channelgroup_pack) { + return srpc_set_pack( + _srpc, channelgroup_pack, channelgroup_pack->count, + &srpc_channelgroup_pack_b_get_caption_size, + &srpc_channelgroup_pack_b_get_item_ptr, + &srpc_channelgroup_pack_b_set_pack_count, + sizeof(TSC_SuplaChannelGroupPack_B), SUPLA_CHANNELGROUP_PACK_MAXCOUNT, + SUPLA_CHANNELGROUP_CAPTION_MAXSIZE, sizeof(TSC_SuplaChannelGroup_B), + SUPLA_SC_CALL_CHANNELGROUP_PACK_UPDATE_B); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_relation_pack_update( + void *_srpc, + TSC_SuplaChannelGroupRelationPack *channelgroup_relation_pack) { + if (channelgroup_relation_pack->count < 1 || + channelgroup_relation_pack->count > + SUPLA_CHANNELGROUP_RELATION_PACK_MAXCOUNT) { + return 0; + } + + unsigned _supla_int_t size = sizeof(TSC_SuplaChannelGroupRelationPack) - + sizeof(channelgroup_relation_pack->items) + + (sizeof(TSC_SuplaChannelGroupRelation) * + channelgroup_relation_pack->count); + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELGROUP_RELATION_PACK_UPDATE, + (char *)channelgroup_relation_pack, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update( + void *_srpc, TSC_SuplaChannelValuePack *channelvalue_pack) { + if (channelvalue_pack->count < 1 || + channelvalue_pack->count > SUPLA_CHANNELVALUE_PACK_MAXCOUNT) { + return 0; + } + + unsigned _supla_int_t size = + sizeof(TSC_SuplaChannelValuePack) - sizeof(channelvalue_pack->items) + + (sizeof(TSC_SuplaChannelValue) * channelvalue_pack->count); + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE, + (char *)channelvalue_pack, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update_b( + void *_srpc, TSC_SuplaChannelValuePack_B *channelvalue_pack) { + if (channelvalue_pack->count < 1 || + channelvalue_pack->count > SUPLA_CHANNELVALUE_PACK_MAXCOUNT) { + return 0; + } + + unsigned _supla_int_t size = + sizeof(TSC_SuplaChannelValuePack_B) - sizeof(channelvalue_pack->items) + + (sizeof(TSC_SuplaChannelValue_B) * channelvalue_pack->count); + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELVALUE_PACK_UPDATE_B, + (char *)channelvalue_pack, size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelextendedvalue_pack_update( + void *_srpc, TSC_SuplaChannelExtendedValuePack *extendedvalue_pack) { + if (extendedvalue_pack == NULL || extendedvalue_pack->count < 1 || + extendedvalue_pack->count > SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXCOUNT || + extendedvalue_pack->pack_size < 1 || + extendedvalue_pack->pack_size > + SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNELEXTENDEDVALUE_PACK_UPDATE, + (char *)extendedvalue_pack, + sizeof(TSC_SuplaChannelExtendedValuePack) - + SUPLA_CHANNELEXTENDEDVALUE_PACK_MAXDATASIZE + + extendedvalue_pack->pack_size); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_get_next(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_GET_NEXT, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_event(void *_srpc, + TSC_SuplaEvent *event) { + _supla_int_t size = sizeof(TSC_SuplaEvent) - SUPLA_SENDER_NAME_MAXSIZE + + event->SenderNameSize; + + if (size > sizeof(TSC_SuplaEvent)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_EVENT, (char *)event, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_value(void *_srpc, TCS_SuplaChannelNewValue *value) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_CHANNEL_SET_VALUE, (char *)value, + sizeof(TCS_SuplaChannelNewValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_channel_value_b( + void *_srpc, TCS_SuplaChannelNewValue_B *value) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_CHANNEL_SET_VALUE_B, + (char *)value, sizeof(TCS_SuplaChannelNewValue_B)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_value(void *_srpc, TCS_SuplaNewValue *value) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_VALUE, (char *)value, + sizeof(TCS_SuplaNewValue)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_OAUTH_TOKEN_REQUEST, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request_result( + void *_srpc, TSC_OAuthTokenRequestResult *result) { + if (result == NULL || result->Token.TokenSize > SUPLA_OAUTH_TOKEN_MAXSIZE) { + return 0; + } + + return srpc_async_call( + _srpc, SUPLA_SC_CALL_OAUTH_TOKEN_REQUEST_RESULT, (char *)result, + sizeof(TSC_OAuthTokenRequestResult) - + (SUPLA_OAUTH_TOKEN_MAXSIZE - result->Token.TokenSize)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_superuser_authorization_request( + void *_srpc, TCS_SuperUserAuthorizationRequest *request) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_SUPERUSER_AUTHORIZATION_REQUEST, + (char *)request, + sizeof(TCS_SuperUserAuthorizationRequest)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_get_superuser_authorization_result(void *_srpc) { + return srpc_async_call( + _srpc, SUPLA_CS_CALL_GET_SUPERUSER_AUTHORIZATION_RESULT, NULL, 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_superuser_authorization_result( + void *_srpc, TSC_SuperUserAuthorizationResult *result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_SUPERUSER_AUTHORIZATION_RESULT, + (char *)result, + sizeof(TSC_SuperUserAuthorizationResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request( + void *_srpc, TCS_DeviceCalCfgRequest *request) { + if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST, + (char *)request, + sizeof(TCS_DeviceCalCfgRequest) - + SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request_b( + void *_srpc, TCS_DeviceCalCfgRequest_B *request) { + if (request == NULL || request->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_CALCFG_REQUEST_B, + (char *)request, + sizeof(TCS_DeviceCalCfgRequest_B) - + SUPLA_CALCFG_DATA_MAXSIZE + request->DataSize); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_calcfg_result( + void *_srpc, TSC_DeviceCalCfgResult *result) { + if (result == NULL || result->DataSize > SUPLA_CALCFG_DATA_MAXSIZE) { + return 0; + } + + return srpc_async_call(_srpc, SUPLA_SC_CALL_DEVICE_CALCFG_RESULT, + (char *)result, + sizeof(TSC_DeviceCalCfgResult) - + SUPLA_CALCFG_DATA_MAXSIZE + result->DataSize); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_get_channel_basic_cfg(void *_srpc, _supla_int_t ChannelID) { + TCS_ChannelBasicCfgRequest request; + memset(&request, 0, sizeof(TCS_ChannelBasicCfgRequest)); + request.ChannelID = ChannelID; + + return srpc_async_call(_srpc, SUPLA_CS_CALL_GET_CHANNEL_BASIC_CFG, + (char *)&request, sizeof(TCS_ChannelBasicCfgRequest)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_basic_cfg_result( + void *_srpc, TSC_ChannelBasicCfg *basic_cfg) { + _supla_int_t size = sizeof(TSC_ChannelBasicCfg) - + SUPLA_CHANNEL_CAPTION_MAXSIZE + basic_cfg->CaptionSize; + + if (size > sizeof(TSC_ChannelBasicCfg)) return 0; + + return srpc_async_call(_srpc, SUPLA_SC_CALL_CHANNEL_BASIC_CFG_RESULT, + (char *)basic_cfg, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_function(void *_srpc, TCS_SetChannelFunction *func) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_CHANNEL_FUNCTION, + (char *)func, sizeof(TCS_SetChannelFunction)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_function_result( + void *_srpc, TSC_SetChannelFunctionResult *result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_SET_CHANNEL_FUNCTION_RESULT, + (char *)result, sizeof(TSC_SetChannelFunctionResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_caption( + void *_srpc, TCS_SetCaption *caption, unsigned _supla_int_t call_type) { + _supla_int_t size = + sizeof(TCS_SetCaption) - SUPLA_CAPTION_MAXSIZE + caption->CaptionSize; + + if (size > sizeof(TCS_SetCaption)) return 0; + + return srpc_async_call(_srpc, call_type, (char *)caption, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_set_caption_result(void *_srpc, TSC_SetCaptionResult *result, + unsigned _supla_int_t call_type) { + _supla_int_t size = sizeof(TSC_SetCaptionResult) - SUPLA_CAPTION_MAXSIZE + + result->CaptionSize; + + if (size > sizeof(TSC_SetCaptionResult)) return 0; + + return srpc_async_call(_srpc, call_type, (char *)result, size); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_caption(void *_srpc, TCS_SetCaption *caption) { + return srpc_cs_async_set_caption(_srpc, caption, + SUPLA_CS_CALL_SET_CHANNEL_CAPTION); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_caption_result( + void *_srpc, TSC_SetCaptionResult *result) { + return srpc_sc_async_set_caption_result( + _srpc, result, SUPLA_SC_CALL_SET_CHANNEL_CAPTION_RESULT); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_location_caption(void *_srpc, TCS_SetCaption *caption) { + return srpc_cs_async_set_caption(_srpc, caption, + SUPLA_CS_CALL_SET_LOCATION_CAPTION); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_location_caption_result( + void *_srpc, TSC_SetCaptionResult *result) { + return srpc_sc_async_set_caption_result( + _srpc, result, SUPLA_SC_CALL_SET_LOCATION_CAPTION_RESULT); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_clients_reconnect_request(void *_srpc) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_CLIENTS_RECONNECT_REQUEST, NULL, + 0); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_clients_reconnect_request_result( + void *_srpc, TSC_ClientsReconnectRequestResult *result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_CLIENTS_RECONNECT_REQUEST_RESULT, + (char *)result, + sizeof(TSC_ClientsReconnectRequestResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_registration_enabled( + void *_srpc, TCS_SetRegistrationEnabled *reg_enabled) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_SET_REGISTRATION_ENABLED, + (char *)reg_enabled, + sizeof(TCS_SetRegistrationEnabled)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_registration_enabled_result( + void *_srpc, TSC_SetRegistrationEnabledResult *result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_SET_REGISTRATION_ENABLED_RESULT, + (char *)result, + sizeof(TSC_SetRegistrationEnabledResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_reconnect_request( + void *_srpc, TCS_DeviceReconnectRequest *request) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_DEVICE_RECONNECT_REQUEST, + (char *)request, sizeof(TCS_DeviceReconnectRequest)); +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_reconnect_request_result( + void *_srpc, TSC_DeviceReconnectRequestResult *result) { + return srpc_async_call(_srpc, SUPLA_SC_CALL_DEVICE_RECONNECT_REQUEST_RESULT, + (char *)result, + sizeof(TSC_DeviceReconnectRequestResult)); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_timer_arm(void *_srpc, TCS_TimerArmRequest *request) { + return srpc_async_call(_srpc, SUPLA_CS_CALL_TIMER_ARM, (char *)request, + sizeof(TCS_TimerArmRequest)); +} + +#endif /*SRPC_EXCLUDE_CLIENT*/ + +#ifndef SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS + +#ifdef USE_DEPRECATED_EMEV_V1 +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_emextended2extended( + TElectricityMeter_ExtendedValue *em_ev, TSuplaChannelExtendedValue *ev) { + if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || + em_ev->m_count < 0) { + return 0; + } + + memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); + ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1; + + ev->size = sizeof(TElectricityMeter_ExtendedValue) - + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + + sizeof(TElectricityMeter_Measurement) * em_ev->m_count; + + if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { + memcpy(ev->value, em_ev, ev->size); + return 1; + } + + ev->size = 0; + return 0; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2emextended( + TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue *em_ev) { + if (em_ev == NULL || ev == NULL || + ev->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V1 || ev->size == 0 || + ev->size > sizeof(TElectricityMeter_ExtendedValue)) { + return 0; + } + + memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue)); + memcpy(em_ev, ev->value, ev->size); + + _supla_int_t expected_size = 0; + + if (em_ev->m_count <= EM_MEASUREMENT_COUNT) { + expected_size = + sizeof(TElectricityMeter_ExtendedValue) - + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + + sizeof(TElectricityMeter_Measurement) * em_ev->m_count; + } + + if (ev->size != expected_size) { + memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue)); + return 0; + } + + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_emev_v1to2(TElectricityMeter_ExtendedValue *v1, + TElectricityMeter_ExtendedValue_V2 *v2) { + if (v1 == NULL || v2 == NULL) { + return 0; + } + memset(v2, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); + + for (int a = 0; a < 3; a++) { + v2->total_forward_active_energy[a] = v1->total_forward_active_energy[a]; + v2->total_reverse_active_energy[a] = v1->total_reverse_active_energy[a]; + v2->total_forward_reactive_energy[a] = v1->total_forward_reactive_energy[a]; + v2->total_reverse_reactive_energy[a] = v1->total_reverse_reactive_energy[a]; + } + + v2->total_cost = v1->total_cost; + v2->price_per_unit = v1->price_per_unit; + memcpy(v2->currency, v1->currency, sizeof(v2->currency)); + v2->measured_values = v1->measured_values; + v2->period = v1->period; + v2->m_count = v1->m_count; + + memcpy(v2->m, v1->m, + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT); + + v2->measured_values ^= + v1->measured_values & EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED; + v2->measured_values ^= + v1->measured_values & EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED; + + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_emev_v2to1(TElectricityMeter_ExtendedValue_V2 *v2, + TElectricityMeter_ExtendedValue *v1) { + if (v1 == NULL || v2 == NULL) { + return 0; + } + memset(v1, 0, sizeof(TElectricityMeter_ExtendedValue)); + + for (int a = 0; a < 3; a++) { + v1->total_forward_active_energy[a] = v2->total_forward_active_energy[a]; + v1->total_reverse_active_energy[a] = v2->total_reverse_active_energy[a]; + v1->total_forward_reactive_energy[a] = v2->total_forward_reactive_energy[a]; + v1->total_reverse_reactive_energy[a] = v2->total_reverse_reactive_energy[a]; + } + + v1->total_cost = v2->total_cost; + v1->price_per_unit = v2->price_per_unit; + memcpy(v1->currency, v2->currency, sizeof(v2->currency)); + v1->measured_values = v2->measured_values; + v1->period = v2->period; + v1->m_count = v2->m_count; + + memcpy(v1->m, v2->m, + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT); + + v1->measured_values ^= + v1->measured_values & EM_VAR_FORWARD_ACTIVE_ENERGY_BALANCED; + v1->measured_values ^= + v1->measured_values & EM_VAR_REVERSE_ACTIVE_ENERGY_BALANCED; + + return 1; +} + +#endif /*USE_DEPRECATED_EMEV_V1*/ + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_emextended2extended( + TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev) { + if (em_ev == NULL || ev == NULL || em_ev->m_count > EM_MEASUREMENT_COUNT || + em_ev->m_count < 0) { + return 0; + } + + memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); + ev->type = EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2; + + ev->size = sizeof(TElectricityMeter_ExtendedValue_V2) - + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + + sizeof(TElectricityMeter_Measurement) * em_ev->m_count; + + if (ev->size > 0 && ev->size <= SUPLA_CHANNELEXTENDEDVALUE_SIZE) { + memcpy(ev->value, em_ev, ev->size); + return 1; + } + + ev->size = 0; + return 0; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_extended2emextended( + TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue_V2 *em_ev) { + if (em_ev == NULL || ev == NULL || + ev->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2 || ev->size == 0 || + ev->size > sizeof(TElectricityMeter_ExtendedValue_V2)) { + return 0; + } + + memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); + memcpy(em_ev, ev->value, ev->size); + + _supla_int_t expected_size = 0; + + if (em_ev->m_count <= EM_MEASUREMENT_COUNT) { + expected_size = + sizeof(TElectricityMeter_ExtendedValue_V2) - + sizeof(TElectricityMeter_Measurement) * EM_MEASUREMENT_COUNT + + sizeof(TElectricityMeter_Measurement) * em_ev->m_count; + } + + if (ev->size != expected_size) { + memset(em_ev, 0, sizeof(TElectricityMeter_ExtendedValue_V2)); + return 0; + } + + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2thermostatextended( + TSuplaChannelExtendedValue *ev, TThermostat_ExtendedValue *th_ev) { + if (ev == NULL || th_ev == NULL || + ev->type != EV_TYPE_THERMOSTAT_DETAILS_V1 || ev->size == 0 || + ev->size > sizeof(TThermostat_ExtendedValue)) { + return 0; + } + + memset(th_ev, 0, sizeof(TThermostat_ExtendedValue)); + memcpy(th_ev, ev->value, ev->size); + + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_thermostatextended2extended( + TThermostat_ExtendedValue *th_ev, TSuplaChannelExtendedValue *ev) { + if (th_ev == NULL || ev == NULL) { + return 0; + } + + memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); + ev->type = EV_TYPE_THERMOSTAT_DETAILS_V1; + ev->size = 0; + + unsigned _supla_int_t size = sizeof(TThermostat_ExtendedValue); + + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Schedule)) { + size -= sizeof(th_ev->Schedule); + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Time)) { + size -= sizeof(th_ev->Time); + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Values)) { + size -= sizeof(th_ev->Values); + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_Flags)) { + size -= sizeof(th_ev->Flags); + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_PresetTemperatures)) { + size -= sizeof(th_ev->PresetTemperature); + if (0 == (th_ev->Fields & THERMOSTAT_FIELD_MeasuredTemperatures)) { + size -= sizeof(th_ev->MeasuredTemperature); + } + } + } + } + } + } + + if (size > 0) { + ev->size = size; + memcpy(ev->value, th_ev, size); + return 1; + } + + return 0; +} + +#ifndef SRPC_EXCLUDE_CLIENT +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_icextended2extended( + TSC_ImpulseCounter_ExtendedValue *ic_ev, TSuplaChannelExtendedValue *ev) { + if (ic_ev == NULL || ev == NULL) { + return 0; + } + + memset(ev, 0, sizeof(TSuplaChannelExtendedValue)); + ev->type = EV_TYPE_IMPULSE_COUNTER_DETAILS_V1; + ev->size = sizeof(TSC_ImpulseCounter_ExtendedValue); + + memcpy(ev->value, ic_ev, ev->size); + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2icextended( + TSuplaChannelExtendedValue *ev, TSC_ImpulseCounter_ExtendedValue *ic_ev) { + if (ic_ev == NULL || ev == NULL || + ev->type != EV_TYPE_IMPULSE_COUNTER_DETAILS_V1 || ev->size == 0 || + ev->size != sizeof(TSC_ImpulseCounter_ExtendedValue)) { + return 0; + } + + memset(ic_ev, 0, sizeof(TSC_ImpulseCounter_ExtendedValue)); + memcpy(ic_ev, ev->value, ev->size); + + return 1; +} + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_value_add( + TSuplaChannelExtendedValue *dest, TSuplaChannelExtendedValue *src) { + if (!dest || !src) { + return 0; + } + + if (src->type == EV_TYPE_NONE || src->size == 0) { + return 0; + } + + if (dest->type == EV_TYPE_NONE) { + memcpy(dest, src, sizeof(TSuplaChannelExtendedValue)); + return 1; + } + + unsigned int src_size = + sizeof(TSuplaChannelExtendedValue) - (sizeof(src->value) - src->size); + + if (dest->type == EV_TYPE_MULTI_VALUE) { + if (dest->size + src_size > sizeof(dest->value)) { + return 0; + } + + memcpy(&dest->value[dest->size], src, src_size); + dest->size += src_size; + return 1; + } + + unsigned int prev_size = + sizeof(TSuplaChannelExtendedValue) - (sizeof(dest->value) - dest->size); + + if (prev_size + src_size > sizeof(dest->value)) { + return 0; + } + + TSuplaChannelExtendedValue prev = {}; + memcpy(&prev, dest, sizeof(TSuplaChannelExtendedValue)); + + dest->type = EV_TYPE_MULTI_VALUE; + dest->size = prev_size; + + memcpy(dest->value, &prev, prev_size); + + return srpc_evtool_value_add(dest, src); +} + +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_value_get(TSuplaChannelExtendedValue *ev, unsigned short index, + TSuplaChannelExtendedValue *dest) { + if (dest == NULL || ev == NULL || ev->type == EV_TYPE_NONE) { + return 0; + } + + if (ev->type == EV_TYPE_MULTI_VALUE) { + unsigned int header_size = + sizeof(TSuplaChannelExtendedValue) - sizeof(ev->value); + unsigned int offset = 0; + unsigned int size = ev->size; + if (size > sizeof(ev->value)) { + size = sizeof(ev->value); + } + size -= header_size; + + unsigned short n = 0; + + while (offset < size) { + TSuplaChannelExtendedValue *next = + (TSuplaChannelExtendedValue *)&ev->value[offset]; + + if (next->type == EV_TYPE_NONE || next->size == 0 || + next->size + offset + header_size > sizeof(ev->value)) { + return 0; + } + + if (n == index) { + memcpy(dest, next, header_size + next->size); + return 1; + } + + offset += header_size + next->size; + n++; + } + } + + if (index == 0) { + memcpy(dest, ev, sizeof(TSuplaChannelExtendedValue)); + return 1; + } + + return 0; +} + +#endif /*SRPC_EXCLUDE_CLIENT*/ + +#endif /*SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS*/ diff --git a/lib/SuplaDevice/src/supla-common/srpc.h b/lib/SuplaDevice/src/supla-common/srpc.h index b3e99628..60d2c18a 100644 --- a/lib/SuplaDevice/src/supla-common/srpc.h +++ b/lib/SuplaDevice/src/supla-common/srpc.h @@ -1,435 +1,435 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef supladex_H_ -#define supladex_H_ - -#include -#include - -#include "eh.h" -#include "proto.h" -#if defined(ESP32) -#include -#endif - -#ifdef __ANDROID__ -#define SRPC_EXCLUDE_DEVICE -#endif /*__ANDROID__*/ - -#if defined(ESP8266) || defined(ESP32) - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#define SRPC_WITHOUT_OUT_QUEUE -#define SRPC_WITHOUT_IN_QUEUE -#endif /* defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) */ - -#define SRPC_EXCLUDE_CLIENT -#define SRPC_ICACHE_FLASH ICACHE_FLASH_ATTR - -#include -#if !defined(ESP32) -#include -#endif -#else -#define SRPC_ICACHE_FLASH -#endif - -#if defined(__AVR__) -#define SRPC_EXCLUDE_CLIENT -#define SRPC_WITHOUT_OUT_QUEUE -#define SRPC_WITHOUT_IN_QUEUE -#endif /*__AVR__*/ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef _supla_int_t (*_func_srpc_DataRW)(void *buf, _supla_int_t count, - void *user_params); -typedef void (*_func_srpc_event_OnRemoteCallReceived)( - void *_srpc, unsigned _supla_int_t rr_id, unsigned _supla_int_t call_type, - void *user_params, unsigned char proto_version); -typedef void (*_func_srpc_event_BeforeCall)(void *_srpc, - unsigned _supla_int_t call_type, - void *user_params); -typedef void (*_func_srpc_event_OnVersionError)(void *_srpc, - unsigned char remote_version, - void *user_params); -typedef void (*_func_srpc_event_OnMinVersionRequired)( - void *_srpc, unsigned _supla_int_t call_type, unsigned char min_version, - void *user_params); - -typedef struct { - _func_srpc_DataRW data_read; - _func_srpc_DataRW data_write; - _func_srpc_event_OnRemoteCallReceived on_remote_call_received; - _func_srpc_event_OnVersionError on_version_error; - _func_srpc_event_BeforeCall before_async_call; - _func_srpc_event_OnMinVersionRequired on_min_version_required; - - TEventHandler *eh; - - void *user_params; -} TsrpcParams; - -union TsrpcDataPacketData { - TDCS_SuplaPingServer *dcs_ping; - TSDC_SuplaPingServerResult *sdc_ping_result; - TSDC_SuplaGetVersionResult *sdc_getversion_result; - TSDC_SuplaVersionError *sdc_version_error; - TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout; - TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result; - TDS_SuplaRegisterDevice *ds_register_device; - TDS_SuplaRegisterDevice_B *ds_register_device_b; - TDS_SuplaRegisterDevice_C *ds_register_device_c; - TDS_SuplaRegisterDevice_D *ds_register_device_d; - TDS_SuplaRegisterDevice_E *ds_register_device_e; - TSD_SuplaRegisterDeviceResult *sd_register_device_result; - TCS_SuplaRegisterClient *cs_register_client; - TCS_SuplaRegisterClient_B *cs_register_client_b; - TCS_SuplaRegisterClient_C *cs_register_client_c; - TCS_SuplaRegisterClient_D *cs_register_client_d; - TSC_SuplaRegisterClientResult *sc_register_client_result; - TSC_SuplaRegisterClientResult_B *sc_register_client_result_b; - TSC_SuplaRegisterClientResult_C *sc_register_client_result_c; - TDS_SuplaDeviceChannelValue *ds_device_channel_value; - TDS_SuplaDeviceChannelValue_B *ds_device_channel_value_b; - TDS_SuplaDeviceChannelValue_C *ds_device_channel_value_c; - TDS_SuplaDeviceChannelExtendedValue *ds_device_channel_extendedvalue; - TSC_SuplaLocation *sc_location; - TSC_SuplaLocationPack *sc_location_pack; - TSC_SuplaChannel *sc_channel; - TSC_SuplaChannel_B *sc_channel_b; - TSC_SuplaChannel_C *sc_channel_c; - TSC_SuplaChannel_D *sc_channel_d; - TSC_SuplaChannelPack *sc_channel_pack; - TSC_SuplaChannelPack_B *sc_channel_pack_b; - TSC_SuplaChannelPack_C *sc_channel_pack_c; - TSC_SuplaChannelPack_D *sc_channel_pack_d; - TSC_SuplaChannelValue *sc_channel_value; - TSC_SuplaChannelValue_B *sc_channel_value_b; - TSC_SuplaEvent *sc_event; - TSD_SuplaChannelNewValue *sd_channel_new_value; - TSD_SuplaChannelGroupNewValue *sd_channelgroup_new_value; - TDS_SuplaChannelNewValueResult *ds_channel_new_value_result; - TCS_SuplaChannelNewValue *cs_channel_new_value; - TCS_SuplaChannelNewValue_B *cs_channel_new_value_b; - TDS_FirmwareUpdateParams *ds_firmware_update_params; - TSD_FirmwareUpdate_UrlResult *sc_firmware_update_url_result; - TSDC_RegistrationEnabled *sdc_reg_enabled; - TSC_SuplaChannelGroupPack *sc_channelgroup_pack; - TSC_SuplaChannelGroupPack_B *sc_channelgroup_pack_b; - TSC_SuplaChannelGroupRelationPack *sc_channelgroup_relation_pack; - TSC_SuplaChannelValuePack *sc_channelvalue_pack; - TSC_SuplaChannelValuePack_B *sc_channelvalue_pack_b; - TSC_SuplaChannelExtendedValuePack *sc_channelextendedvalue_pack; - TCS_SuplaNewValue *cs_new_value; - TSC_OAuthTokenRequestResult *sc_oauth_tokenrequest_result; - TCS_SuperUserAuthorizationRequest *cs_superuser_authorization_request; - TSC_SuperUserAuthorizationResult *sc_superuser_authorization_result; - TCS_DeviceCalCfgRequest *cs_device_calcfg_request; - TCS_DeviceCalCfgRequest_B *cs_device_calcfg_request_b; - TSC_DeviceCalCfgResult *sc_device_calcfg_result; - TSD_DeviceCalCfgRequest *sd_device_calcfg_request; - TDS_DeviceCalCfgResult *ds_device_calcfg_result; - TSDC_UserLocalTimeResult *sdc_user_localtime_result; - TCSD_ChannelStateRequest *csd_channel_state_request; - TDSC_ChannelState *dsc_channel_state; - TCS_ChannelBasicCfgRequest *cs_channel_basic_cfg_request; - TSC_ChannelBasicCfg *sc_channel_basic_cfg; - TCS_SetChannelFunction *cs_set_channel_function; - TSC_SetChannelFunctionResult *sc_set_channel_function_result; - TCS_SetCaption *cs_set_caption; - TSC_SetCaptionResult *sc_set_caption_result; - TSC_ClientsReconnectRequestResult *sc_clients_reconnect_result; - TCS_SetRegistrationEnabled *cs_set_registration_enabled; - TSC_SetRegistrationEnabledResult *sc_set_registration_enabled_result; - TCS_DeviceReconnectRequest *cs_device_reconnect_request; - TSC_DeviceReconnectRequestResult *sc_device_reconnect_request_result; - TSD_ChannelFunctions *sd_channel_functions; - TDS_GetChannelConfigRequest *ds_get_channel_config_request; - TSD_ChannelConfig *sd_channel_config; - TDS_ActionTrigger *ds_action_trigger; - TCS_TimerArmRequest *cs_timer_arm_request; -}; - -typedef struct { - unsigned _supla_int_t call_type; - unsigned _supla_int_t rr_id; - - union TsrpcDataPacketData data; -} TsrpcReceivedData; - -void SRPC_ICACHE_FLASH srpc_params_init(TsrpcParams *params); - -void *SRPC_ICACHE_FLASH srpc_init(TsrpcParams *params); -void SRPC_ICACHE_FLASH srpc_free(void *_srpc); - -char SRPC_ICACHE_FLASH srpc_input_dataexists(void *_srpc); -char SRPC_ICACHE_FLASH srpc_output_dataexists(void *_srpc); -unsigned char SRPC_ICACHE_FLASH srpc_out_queue_item_count(void *srpc); - -char SRPC_ICACHE_FLASH srpc_iterate(void *_srpc); - -char SRPC_ICACHE_FLASH srpc_getdata(void *_srpc, TsrpcReceivedData *rd, - unsigned _supla_int_t rr_id); - -void SRPC_ICACHE_FLASH srpc_rd_free(TsrpcReceivedData *rd); - -unsigned char SRPC_ICACHE_FLASH srpc_get_proto_version(void *_srpc); -void SRPC_ICACHE_FLASH srpc_set_proto_version(void *_srpc, - unsigned char version); - -unsigned char SRPC_ICACHE_FLASH -srpc_call_min_version_required(void *_srpc, unsigned _supla_int_t call_type); -unsigned char SRPC_ICACHE_FLASH -srpc_call_allowed(void *_srpc, unsigned _supla_int_t call_type); - -// device/client <-> server -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_getversion(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_getversion_result( - void *_srpc, char SoftVer[SUPLA_SOFTVER_MAXSIZE]); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sdc_async_versionerror(void *_srpc, unsigned char remote_version); -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_ping_server(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_ping_server_result(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout( - void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout); -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout_result( - void *_srpc, - TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result); -_supla_int_t SRPC_ICACHE_FLASH -srpc_dcs_async_get_registration_enabled(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_registration_enabled_result( - void *_srpc, TSDC_RegistrationEnabled *reg_enabled); -_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_get_user_localtime(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_user_localtime_result( - void *_srpc, TSDC_UserLocalTimeResult *localtime); -_supla_int_t SRPC_ICACHE_FLASH srpc_csd_async_get_channel_state( - void *_srpc, TCSD_ChannelStateRequest *request); -_supla_int_t SRPC_ICACHE_FLASH -srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state); - -#ifndef SRPC_EXCLUDE_DEVICE -// device <-> server -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice( - void *_srpc, TDS_SuplaRegisterDevice *registerdevice); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_b( - void *_srpc, TDS_SuplaRegisterDevice_B *registerdevice); // ver. >= 2 -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_c( - void *_srpc, TDS_SuplaRegisterDevice_C *registerdevice); // ver. >= 6 -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_d( - void *_srpc, TDS_SuplaRegisterDevice_D *registerdevice); // ver. >= 7 -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_e( - void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice); // ver. >= 10 -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_registerdevice_result( - void *_srpc, TSD_SuplaRegisterDeviceResult *registerdevice_result); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed( - void *_srpc, unsigned char channel_number, char *value); -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_channel_value_changed_b(void *_srpc, unsigned char channel_number, - char *value, unsigned char offline); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed_c( - void *_srpc, unsigned char channel_number, char *value, - unsigned char offline, unsigned _supla_int_t validity_time_sec); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_extendedvalue_changed( - void *_srpc, unsigned char channel_number, - TSuplaChannelExtendedValue *value); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sd_async_set_channel_value(void *_srpc, TSD_SuplaChannelNewValue *value); -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_set_channelgroup_value( - void *_srpc, TSD_SuplaChannelGroupNewValue *value); // ver. >= 13 -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, - _supla_int_t SenderID, char Success); -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url( - void *_srpc, TDS_FirmwareUpdateParams *params); -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url_result( - void *_srpc, TSD_FirmwareUpdate_UrlResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_device_calcfg_request( - void *_srpc, TSD_DeviceCalCfgRequest *request); -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_functions(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_functions_result( - void *_srpc, TSD_ChannelFunctions *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_config( - void *_srpc, TDS_GetChannelConfigRequest *request); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sd_async_get_channel_config_result(void *_srpc, TSD_ChannelConfig *config); -_supla_int_t SRPC_ICACHE_FLASH -srpc_ds_async_action_trigger(void *_srpc, TDS_ActionTrigger *action_trigger); -#endif /*SRPC_EXCLUDE_DEVICE*/ - -#ifndef SRPC_EXCLUDE_CLIENT -// client <-> server -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient( - void *_srpc, TCS_SuplaRegisterClient *registerclient); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_b( - void *_srpc, TCS_SuplaRegisterClient_B *registerclient); // ver. >= 6 -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_c( - void *_srpc, TCS_SuplaRegisterClient_C *registerclient); // ver. >= 7 -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_d( - void *_srpc, TCS_SuplaRegisterClient_D *registerclient); // ver. >= 11 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result( - void *_srpc, TSC_SuplaRegisterClientResult *registerclient_result); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_b( - void *_srpc, - TSC_SuplaRegisterClientResult_B *registerclient_result); // ver. >= 9 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_c( - void *_srpc, - TSC_SuplaRegisterClientResult_C *registerclient_result); // ver. >= 17 -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_location_update(void *_srpc, TSC_SuplaLocation *location); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_locationpack_update( - void *_srpc, TSC_SuplaLocationPack *location_pack); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_channel_update(void *_srpc, TSC_SuplaChannel *channel); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_b( - void *_srpc, TSC_SuplaChannel_B *channel); // ver. >= 8 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_c( - void *_srpc, TSC_SuplaChannel_C *channel); // ver. >= 10 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_d( - void *_srpc, TSC_SuplaChannel_D *channel); // ver. >= 15 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update( - void *_srpc, TSC_SuplaChannelPack *channel_pack); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_b( - void *_srpc, TSC_SuplaChannelPack_B *channel_pack); // ver. >= 8 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_c( - void *_srpc, TSC_SuplaChannelPack_C *channel_pack); // ver. >= 10 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_d( - void *_srpc, TSC_SuplaChannelPack_D *channel_pack); // ver. >= 15 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update( - void *_srpc, TSC_SuplaChannelValue *channel_item_value); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update_b( - void *_srpc, TSC_SuplaChannelValue_B *channel_item_value); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update( - void *_srpc, TSC_SuplaChannelGroupPack *channelgroup_pack); // ver. >= 9 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update_b( - void *_srpc, TSC_SuplaChannelGroupPack_B *channelgroup_pack); // ver. >= 10 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_relation_pack_update( - void *_srpc, TSC_SuplaChannelGroupRelationPack - *channelgroup_relation_pack); // ver. >= 9 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update( - void *_srpc, TSC_SuplaChannelValuePack *channelvalue_pack); // ver. >= 9 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update_b( - void *_srpc, TSC_SuplaChannelValuePack_B *channelvalue_pack); // ver. >= 15 -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelextendedvalue_pack_update( - void *_srpc, - TSC_SuplaChannelExtendedValuePack *extendedvalue_pack); // ver. >= 10 -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_get_next(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_event(void *_srpc, - TSC_SuplaEvent *event); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_value(void *_srpc, TCS_SuplaChannelNewValue *value); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_value(void *_srpc, TCS_SuplaNewValue *value); // ver. >= 9 -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_channel_value_b( - void *_srpc, TCS_SuplaChannelNewValue_B *value); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request_result( - void *_srpc, TSC_OAuthTokenRequestResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_superuser_authorization_request( - void *_srpc, TCS_SuperUserAuthorizationRequest *request); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_get_superuser_authorization_result(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_superuser_authorization_result( - void *_srpc, TSC_SuperUserAuthorizationResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request( - void *_srpc, TCS_DeviceCalCfgRequest *request); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request_b( - void *_srpc, TCS_DeviceCalCfgRequest_B *request); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_device_calcfg_result(void *_srpc, TSC_DeviceCalCfgResult *result); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_get_channel_basic_cfg(void *_srpc, _supla_int_t ChannelID); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_basic_cfg_result( - void *_srpc, TSC_ChannelBasicCfg *basic_cfg); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_function(void *_srpc, TCS_SetChannelFunction *func); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_function_result( - void *_srpc, TSC_SetChannelFunctionResult *result); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_channel_caption(void *_srpc, TCS_SetCaption *caption); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_caption_result( - void *_srpc, TSC_SetCaptionResult *caption); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_set_location_caption(void *_srpc, TCS_SetCaption *caption); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_location_caption_result( - void *_srpc, TSC_SetCaptionResult *caption); -_supla_int_t SRPC_ICACHE_FLASH -srpc_cs_async_clients_reconnect_request(void *_srpc); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_clients_reconnect_request_result( - void *_srpc, TSC_ClientsReconnectRequestResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_registration_enabled( - void *_srpc, TCS_SetRegistrationEnabled *reg_enabled); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_registration_enabled_result( - void *_srpc, TSC_SetRegistrationEnabledResult *result); -_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_reconnect_request( - void *_srpc, TCS_DeviceReconnectRequest *request); -_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_reconnect_request_result( - void *_srpc, TSC_DeviceReconnectRequestResult *result); -_supla_int_t SRPC_ICACHE_FLASH -srpc_sc_async_timer_arm(void *_srpc, TCS_TimerArmRequest *request); -#endif /*SRPC_EXCLUDE_CLIENT*/ - -#ifndef SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS -#ifdef USE_DEPRECATED_EMEV_V1 -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_emextended2extended( - TElectricityMeter_ExtendedValue *em_ev, TSuplaChannelExtendedValue *ev); -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2emextended( - TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue *em_ev); - -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_emev_v1to2(TElectricityMeter_ExtendedValue *v1, - TElectricityMeter_ExtendedValue_V2 *v2); -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_emev_v2to1(TElectricityMeter_ExtendedValue_V2 *v2, - TElectricityMeter_ExtendedValue *v1); - -#endif /*USE_DEPRECATED_EMEV_V1*/ - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_emextended2extended( - TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev); -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_extended2emextended( - TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue_V2 *em_ev); - -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2thermostatextended( - TSuplaChannelExtendedValue *ev, TThermostat_ExtendedValue *th_ev); -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_thermostatextended2extended( - TThermostat_ExtendedValue *th_ev, TSuplaChannelExtendedValue *ev); - -#ifndef SRPC_EXCLUDE_CLIENT -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_icextended2extended( - TSC_ImpulseCounter_ExtendedValue *ic_ev, TSuplaChannelExtendedValue *ev); -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2icextended( - TSuplaChannelExtendedValue *ev, TSC_ImpulseCounter_ExtendedValue *ic_ev); -_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_value_add( - TSuplaChannelExtendedValue *dest, TSuplaChannelExtendedValue *src); -_supla_int_t SRPC_ICACHE_FLASH -srpc_evtool_value_get(TSuplaChannelExtendedValue *ev, unsigned short index, - TSuplaChannelExtendedValue *dest); -#endif /*SRPC_EXCLUDE_CLIENT*/ - -#endif /*SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS*/ - -#ifdef __cplusplus -} -#endif - -#endif /* supladex_H_ */ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef supladex_H_ +#define supladex_H_ + +#include +#include + +#include "eh.h" +#include "proto.h" +#if defined(ESP32) +#include +#endif + +#ifdef __ANDROID__ +#define SRPC_EXCLUDE_DEVICE +#endif /*__ANDROID__*/ + +#if defined(ESP8266) || defined(ESP32) + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#define SRPC_WITHOUT_OUT_QUEUE +#define SRPC_WITHOUT_IN_QUEUE +#endif /* defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) */ + +#define SRPC_EXCLUDE_CLIENT +#define SRPC_ICACHE_FLASH ICACHE_FLASH_ATTR + +#include +#if !defined(ESP32) +#include +#endif +#else +#define SRPC_ICACHE_FLASH +#endif + +#if defined(__AVR__) +#define SRPC_EXCLUDE_CLIENT +#define SRPC_WITHOUT_OUT_QUEUE +#define SRPC_WITHOUT_IN_QUEUE +#endif /*__AVR__*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef _supla_int_t (*_func_srpc_DataRW)(void *buf, _supla_int_t count, + void *user_params); +typedef void (*_func_srpc_event_OnRemoteCallReceived)( + void *_srpc, unsigned _supla_int_t rr_id, unsigned _supla_int_t call_type, + void *user_params, unsigned char proto_version); +typedef void (*_func_srpc_event_BeforeCall)(void *_srpc, + unsigned _supla_int_t call_type, + void *user_params); +typedef void (*_func_srpc_event_OnVersionError)(void *_srpc, + unsigned char remote_version, + void *user_params); +typedef void (*_func_srpc_event_OnMinVersionRequired)( + void *_srpc, unsigned _supla_int_t call_type, unsigned char min_version, + void *user_params); + +typedef struct { + _func_srpc_DataRW data_read; + _func_srpc_DataRW data_write; + _func_srpc_event_OnRemoteCallReceived on_remote_call_received; + _func_srpc_event_OnVersionError on_version_error; + _func_srpc_event_BeforeCall before_async_call; + _func_srpc_event_OnMinVersionRequired on_min_version_required; + + TEventHandler *eh; + + void *user_params; +} TsrpcParams; + +union TsrpcDataPacketData { + TDCS_SuplaPingServer *dcs_ping; + TSDC_SuplaPingServerResult *sdc_ping_result; + TSDC_SuplaGetVersionResult *sdc_getversion_result; + TSDC_SuplaVersionError *sdc_version_error; + TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout; + TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result; + TDS_SuplaRegisterDevice *ds_register_device; + TDS_SuplaRegisterDevice_B *ds_register_device_b; + TDS_SuplaRegisterDevice_C *ds_register_device_c; + TDS_SuplaRegisterDevice_D *ds_register_device_d; + TDS_SuplaRegisterDevice_E *ds_register_device_e; + TSD_SuplaRegisterDeviceResult *sd_register_device_result; + TCS_SuplaRegisterClient *cs_register_client; + TCS_SuplaRegisterClient_B *cs_register_client_b; + TCS_SuplaRegisterClient_C *cs_register_client_c; + TCS_SuplaRegisterClient_D *cs_register_client_d; + TSC_SuplaRegisterClientResult *sc_register_client_result; + TSC_SuplaRegisterClientResult_B *sc_register_client_result_b; + TSC_SuplaRegisterClientResult_C *sc_register_client_result_c; + TDS_SuplaDeviceChannelValue *ds_device_channel_value; + TDS_SuplaDeviceChannelValue_B *ds_device_channel_value_b; + TDS_SuplaDeviceChannelValue_C *ds_device_channel_value_c; + TDS_SuplaDeviceChannelExtendedValue *ds_device_channel_extendedvalue; + TSC_SuplaLocation *sc_location; + TSC_SuplaLocationPack *sc_location_pack; + TSC_SuplaChannel *sc_channel; + TSC_SuplaChannel_B *sc_channel_b; + TSC_SuplaChannel_C *sc_channel_c; + TSC_SuplaChannel_D *sc_channel_d; + TSC_SuplaChannelPack *sc_channel_pack; + TSC_SuplaChannelPack_B *sc_channel_pack_b; + TSC_SuplaChannelPack_C *sc_channel_pack_c; + TSC_SuplaChannelPack_D *sc_channel_pack_d; + TSC_SuplaChannelValue *sc_channel_value; + TSC_SuplaChannelValue_B *sc_channel_value_b; + TSC_SuplaEvent *sc_event; + TSD_SuplaChannelNewValue *sd_channel_new_value; + TSD_SuplaChannelGroupNewValue *sd_channelgroup_new_value; + TDS_SuplaChannelNewValueResult *ds_channel_new_value_result; + TCS_SuplaChannelNewValue *cs_channel_new_value; + TCS_SuplaChannelNewValue_B *cs_channel_new_value_b; + TDS_FirmwareUpdateParams *ds_firmware_update_params; + TSD_FirmwareUpdate_UrlResult *sc_firmware_update_url_result; + TSDC_RegistrationEnabled *sdc_reg_enabled; + TSC_SuplaChannelGroupPack *sc_channelgroup_pack; + TSC_SuplaChannelGroupPack_B *sc_channelgroup_pack_b; + TSC_SuplaChannelGroupRelationPack *sc_channelgroup_relation_pack; + TSC_SuplaChannelValuePack *sc_channelvalue_pack; + TSC_SuplaChannelValuePack_B *sc_channelvalue_pack_b; + TSC_SuplaChannelExtendedValuePack *sc_channelextendedvalue_pack; + TCS_SuplaNewValue *cs_new_value; + TSC_OAuthTokenRequestResult *sc_oauth_tokenrequest_result; + TCS_SuperUserAuthorizationRequest *cs_superuser_authorization_request; + TSC_SuperUserAuthorizationResult *sc_superuser_authorization_result; + TCS_DeviceCalCfgRequest *cs_device_calcfg_request; + TCS_DeviceCalCfgRequest_B *cs_device_calcfg_request_b; + TSC_DeviceCalCfgResult *sc_device_calcfg_result; + TSD_DeviceCalCfgRequest *sd_device_calcfg_request; + TDS_DeviceCalCfgResult *ds_device_calcfg_result; + TSDC_UserLocalTimeResult *sdc_user_localtime_result; + TCSD_ChannelStateRequest *csd_channel_state_request; + TDSC_ChannelState *dsc_channel_state; + TCS_ChannelBasicCfgRequest *cs_channel_basic_cfg_request; + TSC_ChannelBasicCfg *sc_channel_basic_cfg; + TCS_SetChannelFunction *cs_set_channel_function; + TSC_SetChannelFunctionResult *sc_set_channel_function_result; + TCS_SetCaption *cs_set_caption; + TSC_SetCaptionResult *sc_set_caption_result; + TSC_ClientsReconnectRequestResult *sc_clients_reconnect_result; + TCS_SetRegistrationEnabled *cs_set_registration_enabled; + TSC_SetRegistrationEnabledResult *sc_set_registration_enabled_result; + TCS_DeviceReconnectRequest *cs_device_reconnect_request; + TSC_DeviceReconnectRequestResult *sc_device_reconnect_request_result; + TSD_ChannelFunctions *sd_channel_functions; + TDS_GetChannelConfigRequest *ds_get_channel_config_request; + TSD_ChannelConfig *sd_channel_config; + TDS_ActionTrigger *ds_action_trigger; + TCS_TimerArmRequest *cs_timer_arm_request; +}; + +typedef struct { + unsigned _supla_int_t call_type; + unsigned _supla_int_t rr_id; + + union TsrpcDataPacketData data; +} TsrpcReceivedData; + +void SRPC_ICACHE_FLASH srpc_params_init(TsrpcParams *params); + +void *SRPC_ICACHE_FLASH srpc_init(TsrpcParams *params); +void SRPC_ICACHE_FLASH srpc_free(void *_srpc); + +char SRPC_ICACHE_FLASH srpc_input_dataexists(void *_srpc); +char SRPC_ICACHE_FLASH srpc_output_dataexists(void *_srpc); +unsigned char SRPC_ICACHE_FLASH srpc_out_queue_item_count(void *srpc); + +char SRPC_ICACHE_FLASH srpc_iterate(void *_srpc); + +char SRPC_ICACHE_FLASH srpc_getdata(void *_srpc, TsrpcReceivedData *rd, + unsigned _supla_int_t rr_id); + +void SRPC_ICACHE_FLASH srpc_rd_free(TsrpcReceivedData *rd); + +unsigned char SRPC_ICACHE_FLASH srpc_get_proto_version(void *_srpc); +void SRPC_ICACHE_FLASH srpc_set_proto_version(void *_srpc, + unsigned char version); + +unsigned char SRPC_ICACHE_FLASH +srpc_call_min_version_required(void *_srpc, unsigned _supla_int_t call_type); +unsigned char SRPC_ICACHE_FLASH +srpc_call_allowed(void *_srpc, unsigned _supla_int_t call_type); + +// device/client <-> server +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_getversion(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_getversion_result( + void *_srpc, char SoftVer[SUPLA_SOFTVER_MAXSIZE]); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sdc_async_versionerror(void *_srpc, unsigned char remote_version); +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_ping_server(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_ping_server_result(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout( + void *_srpc, TDCS_SuplaSetActivityTimeout *dcs_set_activity_timeout); +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_set_activity_timeout_result( + void *_srpc, + TSDC_SuplaSetActivityTimeoutResult *sdc_set_activity_timeout_result); +_supla_int_t SRPC_ICACHE_FLASH +srpc_dcs_async_get_registration_enabled(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_registration_enabled_result( + void *_srpc, TSDC_RegistrationEnabled *reg_enabled); +_supla_int_t SRPC_ICACHE_FLASH srpc_dcs_async_get_user_localtime(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sdc_async_get_user_localtime_result( + void *_srpc, TSDC_UserLocalTimeResult *localtime); +_supla_int_t SRPC_ICACHE_FLASH srpc_csd_async_get_channel_state( + void *_srpc, TCSD_ChannelStateRequest *request); +_supla_int_t SRPC_ICACHE_FLASH +srpc_csd_async_channel_state_result(void *_srpc, TDSC_ChannelState *state); + +#ifndef SRPC_EXCLUDE_DEVICE +// device <-> server +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice( + void *_srpc, TDS_SuplaRegisterDevice *registerdevice); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_b( + void *_srpc, TDS_SuplaRegisterDevice_B *registerdevice); // ver. >= 2 +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_c( + void *_srpc, TDS_SuplaRegisterDevice_C *registerdevice); // ver. >= 6 +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_d( + void *_srpc, TDS_SuplaRegisterDevice_D *registerdevice); // ver. >= 7 +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_registerdevice_e( + void *_srpc, TDS_SuplaRegisterDevice_E *registerdevice); // ver. >= 10 +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_registerdevice_result( + void *_srpc, TSD_SuplaRegisterDeviceResult *registerdevice_result); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed( + void *_srpc, unsigned char channel_number, char *value); +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_channel_value_changed_b(void *_srpc, unsigned char channel_number, + char *value, unsigned char offline); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_value_changed_c( + void *_srpc, unsigned char channel_number, char *value, + unsigned char offline, unsigned _supla_int_t validity_time_sec); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_channel_extendedvalue_changed( + void *_srpc, unsigned char channel_number, + TSuplaChannelExtendedValue *value); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sd_async_set_channel_value(void *_srpc, TSD_SuplaChannelNewValue *value); +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_set_channelgroup_value( + void *_srpc, TSD_SuplaChannelGroupNewValue *value); // ver. >= 13 +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_set_channel_result(void *_srpc, unsigned char ChannelNumber, + _supla_int_t SenderID, char Success); +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url( + void *_srpc, TDS_FirmwareUpdateParams *params); +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_firmware_update_url_result( + void *_srpc, TSD_FirmwareUpdate_UrlResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_device_calcfg_request( + void *_srpc, TSD_DeviceCalCfgRequest *request); +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_device_calcfg_result(void *_srpc, TDS_DeviceCalCfgResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_functions(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sd_async_get_channel_functions_result( + void *_srpc, TSD_ChannelFunctions *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_ds_async_get_channel_config( + void *_srpc, TDS_GetChannelConfigRequest *request); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sd_async_get_channel_config_result(void *_srpc, TSD_ChannelConfig *config); +_supla_int_t SRPC_ICACHE_FLASH +srpc_ds_async_action_trigger(void *_srpc, TDS_ActionTrigger *action_trigger); +#endif /*SRPC_EXCLUDE_DEVICE*/ + +#ifndef SRPC_EXCLUDE_CLIENT +// client <-> server +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient( + void *_srpc, TCS_SuplaRegisterClient *registerclient); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_b( + void *_srpc, TCS_SuplaRegisterClient_B *registerclient); // ver. >= 6 +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_c( + void *_srpc, TCS_SuplaRegisterClient_C *registerclient); // ver. >= 7 +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_registerclient_d( + void *_srpc, TCS_SuplaRegisterClient_D *registerclient); // ver. >= 11 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result( + void *_srpc, TSC_SuplaRegisterClientResult *registerclient_result); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_b( + void *_srpc, + TSC_SuplaRegisterClientResult_B *registerclient_result); // ver. >= 9 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_registerclient_result_c( + void *_srpc, + TSC_SuplaRegisterClientResult_C *registerclient_result); // ver. >= 17 +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_location_update(void *_srpc, TSC_SuplaLocation *location); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_locationpack_update( + void *_srpc, TSC_SuplaLocationPack *location_pack); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_channel_update(void *_srpc, TSC_SuplaChannel *channel); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_b( + void *_srpc, TSC_SuplaChannel_B *channel); // ver. >= 8 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_c( + void *_srpc, TSC_SuplaChannel_C *channel); // ver. >= 10 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_update_d( + void *_srpc, TSC_SuplaChannel_D *channel); // ver. >= 15 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update( + void *_srpc, TSC_SuplaChannelPack *channel_pack); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_b( + void *_srpc, TSC_SuplaChannelPack_B *channel_pack); // ver. >= 8 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_c( + void *_srpc, TSC_SuplaChannelPack_C *channel_pack); // ver. >= 10 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelpack_update_d( + void *_srpc, TSC_SuplaChannelPack_D *channel_pack); // ver. >= 15 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update( + void *_srpc, TSC_SuplaChannelValue *channel_item_value); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_value_update_b( + void *_srpc, TSC_SuplaChannelValue_B *channel_item_value); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update( + void *_srpc, TSC_SuplaChannelGroupPack *channelgroup_pack); // ver. >= 9 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_pack_update_b( + void *_srpc, TSC_SuplaChannelGroupPack_B *channelgroup_pack); // ver. >= 10 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelgroup_relation_pack_update( + void *_srpc, TSC_SuplaChannelGroupRelationPack + *channelgroup_relation_pack); // ver. >= 9 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update( + void *_srpc, TSC_SuplaChannelValuePack *channelvalue_pack); // ver. >= 9 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelvalue_pack_update_b( + void *_srpc, TSC_SuplaChannelValuePack_B *channelvalue_pack); // ver. >= 15 +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channelextendedvalue_pack_update( + void *_srpc, + TSC_SuplaChannelExtendedValuePack *extendedvalue_pack); // ver. >= 10 +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_get_next(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_event(void *_srpc, + TSC_SuplaEvent *event); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_value(void *_srpc, TCS_SuplaChannelNewValue *value); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_value(void *_srpc, TCS_SuplaNewValue *value); // ver. >= 9 +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_channel_value_b( + void *_srpc, TCS_SuplaChannelNewValue_B *value); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_oauth_token_request_result( + void *_srpc, TSC_OAuthTokenRequestResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_superuser_authorization_request( + void *_srpc, TCS_SuperUserAuthorizationRequest *request); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_get_superuser_authorization_result(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_superuser_authorization_result( + void *_srpc, TSC_SuperUserAuthorizationResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request( + void *_srpc, TCS_DeviceCalCfgRequest *request); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_calcfg_request_b( + void *_srpc, TCS_DeviceCalCfgRequest_B *request); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_device_calcfg_result(void *_srpc, TSC_DeviceCalCfgResult *result); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_get_channel_basic_cfg(void *_srpc, _supla_int_t ChannelID); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_channel_basic_cfg_result( + void *_srpc, TSC_ChannelBasicCfg *basic_cfg); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_function(void *_srpc, TCS_SetChannelFunction *func); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_function_result( + void *_srpc, TSC_SetChannelFunctionResult *result); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_channel_caption(void *_srpc, TCS_SetCaption *caption); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_channel_caption_result( + void *_srpc, TSC_SetCaptionResult *caption); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_set_location_caption(void *_srpc, TCS_SetCaption *caption); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_location_caption_result( + void *_srpc, TSC_SetCaptionResult *caption); +_supla_int_t SRPC_ICACHE_FLASH +srpc_cs_async_clients_reconnect_request(void *_srpc); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_clients_reconnect_request_result( + void *_srpc, TSC_ClientsReconnectRequestResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_set_registration_enabled( + void *_srpc, TCS_SetRegistrationEnabled *reg_enabled); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_set_registration_enabled_result( + void *_srpc, TSC_SetRegistrationEnabledResult *result); +_supla_int_t SRPC_ICACHE_FLASH srpc_cs_async_device_reconnect_request( + void *_srpc, TCS_DeviceReconnectRequest *request); +_supla_int_t SRPC_ICACHE_FLASH srpc_sc_async_device_reconnect_request_result( + void *_srpc, TSC_DeviceReconnectRequestResult *result); +_supla_int_t SRPC_ICACHE_FLASH +srpc_sc_async_timer_arm(void *_srpc, TCS_TimerArmRequest *request); +#endif /*SRPC_EXCLUDE_CLIENT*/ + +#ifndef SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS +#ifdef USE_DEPRECATED_EMEV_V1 +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_emextended2extended( + TElectricityMeter_ExtendedValue *em_ev, TSuplaChannelExtendedValue *ev); +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2emextended( + TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue *em_ev); + +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_emev_v1to2(TElectricityMeter_ExtendedValue *v1, + TElectricityMeter_ExtendedValue_V2 *v2); +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_emev_v2to1(TElectricityMeter_ExtendedValue_V2 *v2, + TElectricityMeter_ExtendedValue *v1); + +#endif /*USE_DEPRECATED_EMEV_V1*/ + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_emextended2extended( + TElectricityMeter_ExtendedValue_V2 *em_ev, TSuplaChannelExtendedValue *ev); +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v2_extended2emextended( + TSuplaChannelExtendedValue *ev, TElectricityMeter_ExtendedValue_V2 *em_ev); + +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2thermostatextended( + TSuplaChannelExtendedValue *ev, TThermostat_ExtendedValue *th_ev); +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_thermostatextended2extended( + TThermostat_ExtendedValue *th_ev, TSuplaChannelExtendedValue *ev); + +#ifndef SRPC_EXCLUDE_CLIENT +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_icextended2extended( + TSC_ImpulseCounter_ExtendedValue *ic_ev, TSuplaChannelExtendedValue *ev); +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_v1_extended2icextended( + TSuplaChannelExtendedValue *ev, TSC_ImpulseCounter_ExtendedValue *ic_ev); +_supla_int_t SRPC_ICACHE_FLASH srpc_evtool_value_add( + TSuplaChannelExtendedValue *dest, TSuplaChannelExtendedValue *src); +_supla_int_t SRPC_ICACHE_FLASH +srpc_evtool_value_get(TSuplaChannelExtendedValue *ev, unsigned short index, + TSuplaChannelExtendedValue *dest); +#endif /*SRPC_EXCLUDE_CLIENT*/ + +#endif /*SRPC_EXCLUDE_EXTENDEDVALUE_TOOLS*/ + +#ifdef __cplusplus +} +#endif + +#endif /* supladex_H_ */ diff --git a/lib/SuplaDevice/src/supla/action_handler.cpp b/lib/SuplaDevice/src/supla/action_handler.cpp index 442d02d9..29a29c5e 100644 --- a/lib/SuplaDevice/src/supla/action_handler.cpp +++ b/lib/SuplaDevice/src/supla/action_handler.cpp @@ -1,27 +1,27 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "action_handler.h" - -Supla::ActionHandler::~ActionHandler() {}; - -void Supla::ActionHandler::activateAction(int action) {}; - -bool Supla::ActionHandler::deleteClient() { - return false; -} - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "action_handler.h" + +Supla::ActionHandler::~ActionHandler() {}; + +void Supla::ActionHandler::activateAction(int action) {}; + +bool Supla::ActionHandler::deleteClient() { + return false; +} + + diff --git a/lib/SuplaDevice/src/supla/action_handler.h b/lib/SuplaDevice/src/supla/action_handler.h index 9a8ab13a..551ebd52 100644 --- a/lib/SuplaDevice/src/supla/action_handler.h +++ b/lib/SuplaDevice/src/supla/action_handler.h @@ -1,31 +1,31 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _action_handler_h -#define _action_handler_h - -namespace Supla { -class ActionHandler { - public: - virtual ~ActionHandler(); - virtual void handleAction(int event, int action) = 0; - virtual void activateAction(int action); - virtual bool deleteClient(); -}; - -}; - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _action_handler_h +#define _action_handler_h + +namespace Supla { +class ActionHandler { + public: + virtual ~ActionHandler(); + virtual void handleAction(int event, int action) = 0; + virtual void activateAction(int action); + virtual bool deleteClient(); +}; + +}; + +#endif diff --git a/lib/SuplaDevice/src/supla/actions.h b/lib/SuplaDevice/src/supla/actions.h index b5ddbb2b..d7e8c07c 100644 --- a/lib/SuplaDevice/src/supla/actions.h +++ b/lib/SuplaDevice/src/supla/actions.h @@ -1,95 +1,95 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _actions_h -#define _actions_h - -// Actions are used in ActionHandler elements. They are grouped by most common -// usage, but you should not rely on it. Please check exact supported actions -// in ActionHandler's element documentation - -namespace Supla { -enum Action { - // Relays - TURN_ON, - TURN_OFF, - TOGGLE, - - // Settable binary sensors - SET, - CLEAR, - - // Roller shutters - OPEN, - CLOSE, - STOP, - OPEN_OR_STOP, - CLOSE_OR_STOP, - COMFORT_UP_POSITION, - COMFORT_DOWN_POSITION, - STEP_BY_STEP, - MOVE_UP, - MOVE_DOWN, - MOVE_UP_OR_STOP, - MOVE_DOWN_OR_STOP, - - // Dimmable light, RGB(W) LEDs - BRIGHTEN_ALL, - DIM_ALL, - BRIGHTEN_R, - BRIGHTEN_G, - BRIGHTEN_B, - BRIGHTEN_W, - BRIGHTEN_RGB, - DIM_R, - DIM_G, - DIM_B, - DIM_W, - DIM_RGB, - TURN_ON_RGB, - TURN_OFF_RGB, - TOGGLE_RGB, - TURN_ON_W, - TURN_OFF_W, - TOGGLE_W, - TURN_ON_RGB_DIMMED, - TURN_ON_W_DIMMED, - TURN_ON_ALL_DIMMED, - ITERATE_DIM_RGB, - ITERATE_DIM_W, - ITERATE_DIM_ALL, - - // Impulse counter - RESET, - - // Action trigger - SEND_AT_TURN_ON, - SEND_AT_TURN_OFF, - SEND_AT_TOGGLE_x1, - SEND_AT_TOGGLE_x2, - SEND_AT_TOGGLE_x3, - SEND_AT_TOGGLE_x4, - SEND_AT_TOGGLE_x5, - SEND_AT_HOLD, - SEND_AT_SHORT_PRESS_x1, - SEND_AT_SHORT_PRESS_x2, - SEND_AT_SHORT_PRESS_x3, - SEND_AT_SHORT_PRESS_x4, - SEND_AT_SHORT_PRESS_x5 -}; -}; - -#endif /*_actions_h*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _actions_h +#define _actions_h + +// Actions are used in ActionHandler elements. They are grouped by most common +// usage, but you should not rely on it. Please check exact supported actions +// in ActionHandler's element documentation + +namespace Supla { +enum Action { + // Relays + TURN_ON, + TURN_OFF, + TOGGLE, + + // Settable binary sensors + SET, + CLEAR, + + // Roller shutters + OPEN, + CLOSE, + STOP, + OPEN_OR_STOP, + CLOSE_OR_STOP, + COMFORT_UP_POSITION, + COMFORT_DOWN_POSITION, + STEP_BY_STEP, + MOVE_UP, + MOVE_DOWN, + MOVE_UP_OR_STOP, + MOVE_DOWN_OR_STOP, + + // Dimmable light, RGB(W) LEDs + BRIGHTEN_ALL, + DIM_ALL, + BRIGHTEN_R, + BRIGHTEN_G, + BRIGHTEN_B, + BRIGHTEN_W, + BRIGHTEN_RGB, + DIM_R, + DIM_G, + DIM_B, + DIM_W, + DIM_RGB, + TURN_ON_RGB, + TURN_OFF_RGB, + TOGGLE_RGB, + TURN_ON_W, + TURN_OFF_W, + TOGGLE_W, + TURN_ON_RGB_DIMMED, + TURN_ON_W_DIMMED, + TURN_ON_ALL_DIMMED, + ITERATE_DIM_RGB, + ITERATE_DIM_W, + ITERATE_DIM_ALL, + + // Impulse counter + RESET, + + // Action trigger + SEND_AT_TURN_ON, + SEND_AT_TURN_OFF, + SEND_AT_TOGGLE_x1, + SEND_AT_TOGGLE_x2, + SEND_AT_TOGGLE_x3, + SEND_AT_TOGGLE_x4, + SEND_AT_TOGGLE_x5, + SEND_AT_HOLD, + SEND_AT_SHORT_PRESS_x1, + SEND_AT_SHORT_PRESS_x2, + SEND_AT_SHORT_PRESS_x3, + SEND_AT_SHORT_PRESS_x4, + SEND_AT_SHORT_PRESS_x5 +}; +}; + +#endif /*_actions_h*/ diff --git a/lib/SuplaDevice/src/supla/at_channel.cpp b/lib/SuplaDevice/src/supla/at_channel.cpp index 24ccb03f..9d921b6d 100644 --- a/lib/SuplaDevice/src/supla/at_channel.cpp +++ b/lib/SuplaDevice/src/supla/at_channel.cpp @@ -1,73 +1,73 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "at_channel.h" -#include "supla-common/srpc.h" - -namespace Supla { - - void AtChannel::sendUpdate(void *srpc) { - if (valueChanged) { - TDS_ActionTrigger at = {}; - at.ChannelNumber = getChannelNumber(); - at.ActionTrigger = popAction(); - srpc_ds_async_action_trigger(srpc, &at); - } else { - Channel::sendUpdate(srpc); - } - } - - int AtChannel::popAction() { - for (int i = 0; i < 32; i++) { - if (actionToSend & (1 << i)) { - actionToSend ^= (1 << i); - if (actionToSend == 0) { - clearUpdateReady(); - } - return (1 << i); - } - } - return 0; - } - - void AtChannel::pushAction(int action) { - actionToSend |= action; - setUpdateReady(); - } - - void AtChannel::activateAction(int action) { - setActionTriggerCaps(getActionTriggerCaps() | action); - } - - void AtChannel::setRelatedChannel(uint8_t relatedChannel) { - if (channelNumber >= 0) { - TActionTriggerProperties *prop = - reinterpret_cast - (reg_dev.channels[channelNumber].value); - prop->relatedChannelNumber = relatedChannel + 1; - } - } - - void AtChannel::setDisablesLocalOperation(uint32_t actions) { - if (channelNumber >= 0) { - TActionTriggerProperties *prop = - reinterpret_cast - (reg_dev.channels[channelNumber].value); - prop->disablesLocalOperation = actions; - } - } - -}; +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "at_channel.h" +#include "supla-common/srpc.h" + +namespace Supla { + + void AtChannel::sendUpdate(void *srpc) { + if (valueChanged) { + TDS_ActionTrigger at = {}; + at.ChannelNumber = getChannelNumber(); + at.ActionTrigger = popAction(); + srpc_ds_async_action_trigger(srpc, &at); + } else { + Channel::sendUpdate(srpc); + } + } + + int AtChannel::popAction() { + for (int i = 0; i < 32; i++) { + if (actionToSend & (1 << i)) { + actionToSend ^= (1 << i); + if (actionToSend == 0) { + clearUpdateReady(); + } + return (1 << i); + } + } + return 0; + } + + void AtChannel::pushAction(int action) { + actionToSend |= action; + setUpdateReady(); + } + + void AtChannel::activateAction(int action) { + setActionTriggerCaps(getActionTriggerCaps() | action); + } + + void AtChannel::setRelatedChannel(uint8_t relatedChannel) { + if (channelNumber >= 0) { + TActionTriggerProperties *prop = + reinterpret_cast + (reg_dev.channels[channelNumber].value); + prop->relatedChannelNumber = relatedChannel + 1; + } + } + + void AtChannel::setDisablesLocalOperation(uint32_t actions) { + if (channelNumber >= 0) { + TActionTriggerProperties *prop = + reinterpret_cast + (reg_dev.channels[channelNumber].value); + prop->disablesLocalOperation = actions; + } + } + +}; diff --git a/lib/SuplaDevice/src/supla/at_channel.h b/lib/SuplaDevice/src/supla/at_channel.h index 9570e92a..bf36bb19 100644 --- a/lib/SuplaDevice/src/supla/at_channel.h +++ b/lib/SuplaDevice/src/supla/at_channel.h @@ -1,39 +1,39 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _at_channel_h -#define _at_channel_h - -#include "channel.h" - -namespace Supla { - -class AtChannel : public Channel { - public: - void sendUpdate(void *srpc) override; - void pushAction(int action); - void activateAction(int action); - int popAction(); - void setRelatedChannel(uint8_t channelNumber); - void setDisablesLocalOperation(uint32_t actions); - - protected: - int actionToSend = 0; -}; - -}; - -#endif /*_at_channel_h*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _at_channel_h +#define _at_channel_h + +#include "channel.h" + +namespace Supla { + +class AtChannel : public Channel { + public: + void sendUpdate(void *srpc) override; + void pushAction(int action); + void activateAction(int action); + int popAction(); + void setRelatedChannel(uint8_t channelNumber); + void setDisablesLocalOperation(uint32_t actions); + + protected: + int actionToSend = 0; +}; + +}; + +#endif /*_at_channel_h*/ diff --git a/lib/SuplaDevice/src/supla/channel.cpp b/lib/SuplaDevice/src/supla/channel.cpp index 31d54c8b..590bd02f 100644 --- a/lib/SuplaDevice/src/supla/channel.cpp +++ b/lib/SuplaDevice/src/supla/channel.cpp @@ -1,392 +1,392 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include "supla/channel.h" -#include "supla-common/log.h" -#include "supla-common/srpc.h" -#include "tools.h" -#include "events.h" -#include "correction.h" - -namespace Supla { - -unsigned long Channel::lastCommunicationTimeMs = 0; -TDS_SuplaRegisterDevice_E Channel::reg_dev; - -Channel::Channel() : valueChanged(false), channelConfig(false), - channelNumber(-1), validityTimeSec(0) { - if (reg_dev.channel_count < SUPLA_CHANNELMAXCOUNT) { - channelNumber = reg_dev.channel_count; - - memset(®_dev.channels[channelNumber], 0, - sizeof(reg_dev.channels[channelNumber])); - reg_dev.channels[channelNumber].Number = channelNumber; - - reg_dev.channel_count++; - } else { -// TODO: add status CHANNEL_LIMIT_EXCEEDED - } - - setFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); -} - -Channel::~Channel() { - reg_dev.channel_count--; -} - -void Channel::setNewValue(double dbl) { - // Apply channel value correction - dbl += Correction::get(getChannelNumber()); - - char newValue[SUPLA_CHANNELVALUE_SIZE]; - if (sizeof(double) == 8) { - memcpy(newValue, &dbl, 8); - } else if (sizeof(double) == 4) { - float2DoublePacked(dbl, (uint8_t *)(newValue)); - } - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log(LOG_DEBUG, "Channel(%d) value changed to %d.%d", channelNumber, static_cast(dbl), static_cast(dbl*100)%100); - } -} - -void Channel::setNewValue(double temp, double humi) { - // Apply channel value corrections - temp += Correction::get(getChannelNumber()); - humi += Correction::get(getChannelNumber(), true); - - char newValue[SUPLA_CHANNELVALUE_SIZE]; - _supla_int_t t = temp * 1000.00; - _supla_int_t h = humi * 1000.00; - - memcpy(newValue, &t, 4); - memcpy(&(newValue[4]), &h, 4); - - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log(LOG_DEBUG, - "Channel(%d) value changed to temp(%f), humi(%f)", - channelNumber, - temp, - humi); - } -} - -void Channel::setNewValue(unsigned _supla_int64_t value) { - char newValue[SUPLA_CHANNELVALUE_SIZE]; - - memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); - - memcpy(newValue, &value, sizeof(value)); - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log( - LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, static_cast(value)); - } -} - -void Channel::setNewValue(_supla_int_t value) { - char newValue[SUPLA_CHANNELVALUE_SIZE]; - - memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); - - memcpy(newValue, &value, sizeof(value)); - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log( - LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value); - } -} - -void Channel::setNewValue(bool value) { - char newValue[SUPLA_CHANNELVALUE_SIZE]; - - memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); - - newValue[0] = value; - if (setNewValue(newValue)) { - if (value) { - runAction(Supla::ON_TURN_ON); - } else { - runAction(Supla::ON_TURN_OFF); - } - runAction(Supla::ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - - supla_log( - LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value); - } -} - -void Channel::setNewValue(TElectricityMeter_ExtendedValue_V2 &emValue) { - // Prepare standard channel value - if (sizeof(TElectricityMeter_Value) <= SUPLA_CHANNELVALUE_SIZE) { - TElectricityMeter_Measurement *m = nullptr; - TElectricityMeter_Value v; - memset(&v, 0, sizeof(TElectricityMeter_Value)); - - unsigned _supla_int64_t fae_sum = emValue.total_forward_active_energy[0] + - emValue.total_forward_active_energy[1] + - emValue.total_forward_active_energy[2]; - - v.total_forward_active_energy = fae_sum / 1000; - - if (emValue.m_count && emValue.measured_values & EM_VAR_VOLTAGE) { - m = &emValue.m[emValue.m_count - 1]; - - if (m->voltage[0] > 0) { - v.flags |= EM_VALUE_FLAG_PHASE1_ON; - } - - if (m->voltage[1] > 0) { - v.flags |= EM_VALUE_FLAG_PHASE2_ON; - } - - if (m->voltage[2] > 0) { - v.flags |= EM_VALUE_FLAG_PHASE3_ON; - } - } - - memcpy(reg_dev.channels[channelNumber].value, - &v, - sizeof(TElectricityMeter_Value)); - setUpdateReady(); - } -} - -bool Channel::setNewValue(char *newValue) { - if (memcmp(newValue, reg_dev.channels[channelNumber].value, 8) != 0) { - memcpy(reg_dev.channels[channelNumber].value, newValue, 8); - setUpdateReady(); - return true; - } - return false; -} - -void Channel::setType(_supla_int_t type) { - if (channelNumber >= 0) { - reg_dev.channels[channelNumber].Type = type; - } -} - -void Channel::setDefault(_supla_int_t value) { - if (channelNumber >= 0) { - reg_dev.channels[channelNumber].Default = value; - } -} - -void Channel::setFlag(_supla_int_t flag) { - if (channelNumber >= 0) { - reg_dev.channels[channelNumber].Flags |= flag; - } -} - -void Channel::unsetFlag(_supla_int_t flag) { - if (channelNumber >= 0) { - reg_dev.channels[channelNumber].Flags &= ~flag; - } -} - -void Channel::setFuncList(_supla_int_t functions) { - if (channelNumber >= 0) { - reg_dev.channels[channelNumber].FuncList = functions; - } -} - -_supla_int_t Channel::getFuncList() { - if (channelNumber >= 0) { - return reg_dev.channels[channelNumber].FuncList; - } - return 0; -} - -void Channel::setActionTriggerCaps(_supla_int_t caps) { - supla_log(LOG_DEBUG, "Channel[%d] setting func list: %d", channelNumber, caps); - setFuncList(caps); -} - -_supla_int_t Channel::getActionTriggerCaps() { - return getFuncList(); -} - -int Channel::getChannelNumber() { - return channelNumber; -} - -void Channel::clearUpdateReady() { - valueChanged = false; -}; - -void Channel::sendUpdate(void *srpc) { - if (valueChanged) { - clearUpdateReady(); - srpc_ds_async_channel_value_changed_c( - srpc, channelNumber, reg_dev.channels[channelNumber].value, - 0, validityTimeSec); - - // returns null for non-extended channels - TSuplaChannelExtendedValue *extValue = getExtValue(); - if (extValue) { - srpc_ds_async_channel_extendedvalue_changed(srpc, channelNumber, extValue); - } - } - - // send channel config request if needed - if (channelConfig) { - channelConfig = false; - channelConfig = false; - TDS_GetChannelConfigRequest request = {}; - request.ChannelNumber = getChannelNumber(); - srpc_ds_async_get_channel_config(srpc, &request); - } -} - -TSuplaChannelExtendedValue *Channel::getExtValue() { - return nullptr; -} - -void Channel::setUpdateReady() { - valueChanged = true; -}; - -bool Channel::isUpdateReady() { - return valueChanged || channelConfig; -}; - -bool Channel::isExtended() { - return false; -} - -void Channel::setNewValue(const TRollerShutterValue &value) { - char newValue[SUPLA_CHANNELVALUE_SIZE] = {}; - memcpy(newValue, &value, sizeof(TRollerShutterValue)); - - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log( - LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value.position); - } - -} - -void Channel::setNewValue(uint8_t red, - uint8_t green, - uint8_t blue, - uint8_t colorBrightness, - uint8_t brightness) { - char newValue[SUPLA_CHANNELVALUE_SIZE]; - memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); - newValue[0] = brightness; - newValue[1] = colorBrightness; - newValue[2] = blue; - newValue[3] = green; - newValue[4] = red; - if (setNewValue(newValue)) { - runAction(ON_CHANGE); - runAction(ON_SECONDARY_CHANNEL_CHANGE); - supla_log(LOG_DEBUG, "Channel(%d) value changed to RGB(%d, %d, %d), colBr(%d), bright(%d)", channelNumber, red, green, blue, colorBrightness, brightness); - } -} - -_supla_int_t Channel::getChannelType() { - if (channelNumber >= 0) { - return reg_dev.channels[channelNumber].Type; - } - return -1; -} - -double Channel::getValueDouble() { - double value; - if (sizeof(double) == 8) { - memcpy(&value, reg_dev.channels[channelNumber].value, 8); - } else if (sizeof(double) == 4) { - value = doublePacked2float((uint8_t *)(reg_dev.channels[channelNumber].value)); - } - - return value; -} - -double Channel::getValueDoubleFirst() { - _supla_int_t value; - memcpy(&value, reg_dev.channels[channelNumber].value, 4); - - return value / 1000.0; -} - -double Channel::getValueDoubleSecond() { - _supla_int_t value; - memcpy(&value, &(reg_dev.channels[channelNumber].value[4]), 4); - - return value / 1000.0; -} - -_supla_int_t Channel::getValueInt32() { - _supla_int_t value; - memcpy(&value, reg_dev.channels[channelNumber].value, sizeof(value)); - return value; -} - -unsigned _supla_int64_t Channel::getValueInt64() { - unsigned _supla_int64_t value; - memcpy(&value, reg_dev.channels[channelNumber].value, sizeof(value)); - return value; -} - -bool Channel::getValueBool() { - return reg_dev.channels[channelNumber].value[0]; -} - -uint8_t Channel::getValueRed() { - return reg_dev.channels[channelNumber].value[4]; -} - -uint8_t Channel::getValueGreen() { - return reg_dev.channels[channelNumber].value[3]; -} - -uint8_t Channel::getValueBlue() { - return reg_dev.channels[channelNumber].value[2]; -} - -uint8_t Channel::getValueColorBrightness() { - return reg_dev.channels[channelNumber].value[1]; -} - -uint8_t Channel::getValueBrightness() { - return reg_dev.channels[channelNumber].value[0]; -} - -void Channel::setValidityTimeSec(unsigned _supla_int_t timeSec) { - validityTimeSec = timeSec; - if (validityTimeSec > 0) unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); -} - -void Channel::setCorrection(double correction, bool forSecondaryValue) { - Correction::add(getChannelNumber(), correction, forSecondaryValue); -} - -void Channel::requestChannelConfig() { - channelConfig = true; -} - -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "supla/channel.h" +#include "supla-common/log.h" +#include "supla-common/srpc.h" +#include "tools.h" +#include "events.h" +#include "correction.h" + +namespace Supla { + +unsigned long Channel::lastCommunicationTimeMs = 0; +TDS_SuplaRegisterDevice_E Channel::reg_dev; + +Channel::Channel() : valueChanged(false), channelConfig(false), + channelNumber(-1), validityTimeSec(0) { + if (reg_dev.channel_count < SUPLA_CHANNELMAXCOUNT) { + channelNumber = reg_dev.channel_count; + + memset(®_dev.channels[channelNumber], 0, + sizeof(reg_dev.channels[channelNumber])); + reg_dev.channels[channelNumber].Number = channelNumber; + + reg_dev.channel_count++; + } else { +// TODO: add status CHANNEL_LIMIT_EXCEEDED + } + + setFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); +} + +Channel::~Channel() { + reg_dev.channel_count--; +} + +void Channel::setNewValue(double dbl) { + // Apply channel value correction + dbl += Correction::get(getChannelNumber()); + + char newValue[SUPLA_CHANNELVALUE_SIZE]; + if (sizeof(double) == 8) { + memcpy(newValue, &dbl, 8); + } else if (sizeof(double) == 4) { + float2DoublePacked(dbl, (uint8_t *)(newValue)); + } + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log(LOG_DEBUG, "Channel(%d) value changed to %d.%d", channelNumber, static_cast(dbl), static_cast(dbl*100)%100); + } +} + +void Channel::setNewValue(double temp, double humi) { + // Apply channel value corrections + temp += Correction::get(getChannelNumber()); + humi += Correction::get(getChannelNumber(), true); + + char newValue[SUPLA_CHANNELVALUE_SIZE]; + _supla_int_t t = temp * 1000.00; + _supla_int_t h = humi * 1000.00; + + memcpy(newValue, &t, 4); + memcpy(&(newValue[4]), &h, 4); + + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log(LOG_DEBUG, + "Channel(%d) value changed to temp(%f), humi(%f)", + channelNumber, + temp, + humi); + } +} + +void Channel::setNewValue(unsigned _supla_int64_t value) { + char newValue[SUPLA_CHANNELVALUE_SIZE]; + + memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); + + memcpy(newValue, &value, sizeof(value)); + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log( + LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, static_cast(value)); + } +} + +void Channel::setNewValue(_supla_int_t value) { + char newValue[SUPLA_CHANNELVALUE_SIZE]; + + memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); + + memcpy(newValue, &value, sizeof(value)); + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log( + LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value); + } +} + +void Channel::setNewValue(bool value) { + char newValue[SUPLA_CHANNELVALUE_SIZE]; + + memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); + + newValue[0] = value; + if (setNewValue(newValue)) { + if (value) { + runAction(Supla::ON_TURN_ON); + } else { + runAction(Supla::ON_TURN_OFF); + } + runAction(Supla::ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + + supla_log( + LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value); + } +} + +void Channel::setNewValue(TElectricityMeter_ExtendedValue_V2 &emValue) { + // Prepare standard channel value + if (sizeof(TElectricityMeter_Value) <= SUPLA_CHANNELVALUE_SIZE) { + TElectricityMeter_Measurement *m = nullptr; + TElectricityMeter_Value v; + memset(&v, 0, sizeof(TElectricityMeter_Value)); + + unsigned _supla_int64_t fae_sum = emValue.total_forward_active_energy[0] + + emValue.total_forward_active_energy[1] + + emValue.total_forward_active_energy[2]; + + v.total_forward_active_energy = fae_sum / 1000; + + if (emValue.m_count && emValue.measured_values & EM_VAR_VOLTAGE) { + m = &emValue.m[emValue.m_count - 1]; + + if (m->voltage[0] > 0) { + v.flags |= EM_VALUE_FLAG_PHASE1_ON; + } + + if (m->voltage[1] > 0) { + v.flags |= EM_VALUE_FLAG_PHASE2_ON; + } + + if (m->voltage[2] > 0) { + v.flags |= EM_VALUE_FLAG_PHASE3_ON; + } + } + + memcpy(reg_dev.channels[channelNumber].value, + &v, + sizeof(TElectricityMeter_Value)); + setUpdateReady(); + } +} + +bool Channel::setNewValue(char *newValue) { + if (memcmp(newValue, reg_dev.channels[channelNumber].value, 8) != 0) { + memcpy(reg_dev.channels[channelNumber].value, newValue, 8); + setUpdateReady(); + return true; + } + return false; +} + +void Channel::setType(_supla_int_t type) { + if (channelNumber >= 0) { + reg_dev.channels[channelNumber].Type = type; + } +} + +void Channel::setDefault(_supla_int_t value) { + if (channelNumber >= 0) { + reg_dev.channels[channelNumber].Default = value; + } +} + +void Channel::setFlag(_supla_int_t flag) { + if (channelNumber >= 0) { + reg_dev.channels[channelNumber].Flags |= flag; + } +} + +void Channel::unsetFlag(_supla_int_t flag) { + if (channelNumber >= 0) { + reg_dev.channels[channelNumber].Flags &= ~flag; + } +} + +void Channel::setFuncList(_supla_int_t functions) { + if (channelNumber >= 0) { + reg_dev.channels[channelNumber].FuncList = functions; + } +} + +_supla_int_t Channel::getFuncList() { + if (channelNumber >= 0) { + return reg_dev.channels[channelNumber].FuncList; + } + return 0; +} + +void Channel::setActionTriggerCaps(_supla_int_t caps) { + supla_log(LOG_DEBUG, "Channel[%d] setting func list: %d", channelNumber, caps); + setFuncList(caps); +} + +_supla_int_t Channel::getActionTriggerCaps() { + return getFuncList(); +} + +int Channel::getChannelNumber() { + return channelNumber; +} + +void Channel::clearUpdateReady() { + valueChanged = false; +}; + +void Channel::sendUpdate(void *srpc) { + if (valueChanged) { + clearUpdateReady(); + srpc_ds_async_channel_value_changed_c( + srpc, channelNumber, reg_dev.channels[channelNumber].value, + 0, validityTimeSec); + + // returns null for non-extended channels + TSuplaChannelExtendedValue *extValue = getExtValue(); + if (extValue) { + srpc_ds_async_channel_extendedvalue_changed(srpc, channelNumber, extValue); + } + } + + // send channel config request if needed + if (channelConfig) { + channelConfig = false; + channelConfig = false; + TDS_GetChannelConfigRequest request = {}; + request.ChannelNumber = getChannelNumber(); + srpc_ds_async_get_channel_config(srpc, &request); + } +} + +TSuplaChannelExtendedValue *Channel::getExtValue() { + return nullptr; +} + +void Channel::setUpdateReady() { + valueChanged = true; +}; + +bool Channel::isUpdateReady() { + return valueChanged || channelConfig; +}; + +bool Channel::isExtended() { + return false; +} + +void Channel::setNewValue(const TRollerShutterValue &value) { + char newValue[SUPLA_CHANNELVALUE_SIZE] = {}; + memcpy(newValue, &value, sizeof(TRollerShutterValue)); + + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log( + LOG_DEBUG, "Channel(%d) value changed to %d", channelNumber, value.position); + } + +} + +void Channel::setNewValue(uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t colorBrightness, + uint8_t brightness) { + char newValue[SUPLA_CHANNELVALUE_SIZE]; + memset(newValue, 0, SUPLA_CHANNELVALUE_SIZE); + newValue[0] = brightness; + newValue[1] = colorBrightness; + newValue[2] = blue; + newValue[3] = green; + newValue[4] = red; + if (setNewValue(newValue)) { + runAction(ON_CHANGE); + runAction(ON_SECONDARY_CHANNEL_CHANGE); + supla_log(LOG_DEBUG, "Channel(%d) value changed to RGB(%d, %d, %d), colBr(%d), bright(%d)", channelNumber, red, green, blue, colorBrightness, brightness); + } +} + +_supla_int_t Channel::getChannelType() { + if (channelNumber >= 0) { + return reg_dev.channels[channelNumber].Type; + } + return -1; +} + +double Channel::getValueDouble() { + double value; + if (sizeof(double) == 8) { + memcpy(&value, reg_dev.channels[channelNumber].value, 8); + } else if (sizeof(double) == 4) { + value = doublePacked2float((uint8_t *)(reg_dev.channels[channelNumber].value)); + } + + return value; +} + +double Channel::getValueDoubleFirst() { + _supla_int_t value; + memcpy(&value, reg_dev.channels[channelNumber].value, 4); + + return value / 1000.0; +} + +double Channel::getValueDoubleSecond() { + _supla_int_t value; + memcpy(&value, &(reg_dev.channels[channelNumber].value[4]), 4); + + return value / 1000.0; +} + +_supla_int_t Channel::getValueInt32() { + _supla_int_t value; + memcpy(&value, reg_dev.channels[channelNumber].value, sizeof(value)); + return value; +} + +unsigned _supla_int64_t Channel::getValueInt64() { + unsigned _supla_int64_t value; + memcpy(&value, reg_dev.channels[channelNumber].value, sizeof(value)); + return value; +} + +bool Channel::getValueBool() { + return reg_dev.channels[channelNumber].value[0]; +} + +uint8_t Channel::getValueRed() { + return reg_dev.channels[channelNumber].value[4]; +} + +uint8_t Channel::getValueGreen() { + return reg_dev.channels[channelNumber].value[3]; +} + +uint8_t Channel::getValueBlue() { + return reg_dev.channels[channelNumber].value[2]; +} + +uint8_t Channel::getValueColorBrightness() { + return reg_dev.channels[channelNumber].value[1]; +} + +uint8_t Channel::getValueBrightness() { + return reg_dev.channels[channelNumber].value[0]; +} + +void Channel::setValidityTimeSec(unsigned _supla_int_t timeSec) { + validityTimeSec = timeSec; + if (validityTimeSec > 0) unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); +} + +void Channel::setCorrection(double correction, bool forSecondaryValue) { + Correction::add(getChannelNumber(), correction, forSecondaryValue); +} + +void Channel::requestChannelConfig() { + channelConfig = true; +} + +}; // namespace Supla diff --git a/lib/SuplaDevice/src/supla/channel.h b/lib/SuplaDevice/src/supla/channel.h index 1e2b423d..3ecce33f 100644 --- a/lib/SuplaDevice/src/supla/channel.h +++ b/lib/SuplaDevice/src/supla/channel.h @@ -1,94 +1,94 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _channel_h -#define _channel_h - -#include - -#include "supla-common/proto.h" -#include "local_action.h" - -namespace Supla { - -class Channel : public LocalAction { - public: - Channel(); - virtual ~Channel(); - - void setNewValue(double dbl); - void setNewValue(double temp, double humi); - void setNewValue(_supla_int_t value); - void setNewValue(bool value); - void setNewValue(TElectricityMeter_ExtendedValue_V2 &emValue); - void setNewValue(uint8_t red, - uint8_t green, - uint8_t blue, - uint8_t colorBrightness, - uint8_t brightness); - void setNewValue(unsigned _supla_int64_t value); - void setNewValue(const TRollerShutterValue &value); - bool setNewValue(char *newValue); - - double getValueDouble(); - double getValueDoubleFirst(); - double getValueDoubleSecond(); - _supla_int_t getValueInt32(); - unsigned _supla_int64_t getValueInt64(); - bool getValueBool(); - uint8_t getValueRed(); - uint8_t getValueGreen(); - uint8_t getValueBlue(); - uint8_t getValueColorBrightness(); - uint8_t getValueBrightness(); - - virtual bool isExtended(); - bool isUpdateReady(); - int getChannelNumber(); - _supla_int_t getChannelType(); - - void setType(_supla_int_t type); - void setDefault(_supla_int_t value); - void setFlag(_supla_int_t flag); - void unsetFlag(_supla_int_t flag); - void setFuncList(_supla_int_t functions); - _supla_int_t getFuncList(); - void setActionTriggerCaps(_supla_int_t caps); - _supla_int_t getActionTriggerCaps(); - - void setValidityTimeSec(unsigned _supla_int_t); - void clearUpdateReady(); - virtual void sendUpdate(void *srpc); - virtual TSuplaChannelExtendedValue *getExtValue(); - void setCorrection(double correction, bool forSecondaryValue = false); - - void requestChannelConfig(); - - static unsigned long lastCommunicationTimeMs; - static TDS_SuplaRegisterDevice_E reg_dev; - - protected: - void setUpdateReady(); - - bool valueChanged; - bool channelConfig; - int channelNumber; - unsigned _supla_int_t validityTimeSec; -}; - -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _channel_h +#define _channel_h + +#include + +#include "supla-common/proto.h" +#include "local_action.h" + +namespace Supla { + +class Channel : public LocalAction { + public: + Channel(); + virtual ~Channel(); + + void setNewValue(double dbl); + void setNewValue(double temp, double humi); + void setNewValue(_supla_int_t value); + void setNewValue(bool value); + void setNewValue(TElectricityMeter_ExtendedValue_V2 &emValue); + void setNewValue(uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t colorBrightness, + uint8_t brightness); + void setNewValue(unsigned _supla_int64_t value); + void setNewValue(const TRollerShutterValue &value); + bool setNewValue(char *newValue); + + double getValueDouble(); + double getValueDoubleFirst(); + double getValueDoubleSecond(); + _supla_int_t getValueInt32(); + unsigned _supla_int64_t getValueInt64(); + bool getValueBool(); + uint8_t getValueRed(); + uint8_t getValueGreen(); + uint8_t getValueBlue(); + uint8_t getValueColorBrightness(); + uint8_t getValueBrightness(); + + virtual bool isExtended(); + bool isUpdateReady(); + int getChannelNumber(); + _supla_int_t getChannelType(); + + void setType(_supla_int_t type); + void setDefault(_supla_int_t value); + void setFlag(_supla_int_t flag); + void unsetFlag(_supla_int_t flag); + void setFuncList(_supla_int_t functions); + _supla_int_t getFuncList(); + void setActionTriggerCaps(_supla_int_t caps); + _supla_int_t getActionTriggerCaps(); + + void setValidityTimeSec(unsigned _supla_int_t); + void clearUpdateReady(); + virtual void sendUpdate(void *srpc); + virtual TSuplaChannelExtendedValue *getExtValue(); + void setCorrection(double correction, bool forSecondaryValue = false); + + void requestChannelConfig(); + + static unsigned long lastCommunicationTimeMs; + static TDS_SuplaRegisterDevice_E reg_dev; + + protected: + void setUpdateReady(); + + bool valueChanged; + bool channelConfig; + int channelNumber; + unsigned _supla_int_t validityTimeSec; +}; + +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/channel_element.cpp b/lib/SuplaDevice/src/supla/channel_element.cpp index b06121db..594697e3 100644 --- a/lib/SuplaDevice/src/supla/channel_element.cpp +++ b/lib/SuplaDevice/src/supla/channel_element.cpp @@ -1,45 +1,45 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "channel_element.h" -#include "events.h" - -Supla::Channel *Supla::ChannelElement::getChannel() { - return &channel; -} - -void Supla::ChannelElement::addAction(int action, ActionHandler &client, int event) { - channel.addAction(action, client, event); -} - -void Supla::ChannelElement::addAction(int action, ActionHandler *client, int event) { - addAction(action, *client, event); -} - -bool Supla::ChannelElement::isEventAlreadyUsed(int event) { - return channel.isEventAlreadyUsed(event); -} - -void Supla::ChannelElement::addAction(int action, ActionHandler &client, Supla::Condition *condition) { - condition->setClient(client); - condition->setSource(this); - channel.addAction(action, condition, Supla::ON_CHANGE); -} - -void Supla::ChannelElement::addAction(int action, ActionHandler *client, Supla::Condition *condition) { - addAction(action, *client, condition); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "channel_element.h" +#include "events.h" + +Supla::Channel *Supla::ChannelElement::getChannel() { + return &channel; +} + +void Supla::ChannelElement::addAction(int action, ActionHandler &client, int event) { + channel.addAction(action, client, event); +} + +void Supla::ChannelElement::addAction(int action, ActionHandler *client, int event) { + addAction(action, *client, event); +} + +bool Supla::ChannelElement::isEventAlreadyUsed(int event) { + return channel.isEventAlreadyUsed(event); +} + +void Supla::ChannelElement::addAction(int action, ActionHandler &client, Supla::Condition *condition) { + condition->setClient(client); + condition->setSource(this); + channel.addAction(action, condition, Supla::ON_CHANGE); +} + +void Supla::ChannelElement::addAction(int action, ActionHandler *client, Supla::Condition *condition) { + addAction(action, *client, condition); +} + diff --git a/lib/SuplaDevice/src/supla/channel_element.h b/lib/SuplaDevice/src/supla/channel_element.h index 7e17d218..32d4068a 100644 --- a/lib/SuplaDevice/src/supla/channel_element.h +++ b/lib/SuplaDevice/src/supla/channel_element.h @@ -1,50 +1,50 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _channel_element_h -#define _channel_element_h - -#include "element.h" -#include "channel.h" -#include "local_action.h" -#include "action_handler.h" -#include "condition.h" - -namespace Supla { - -class Condition; - -class ChannelElement : public Element, public LocalAction { - public: - - Channel *getChannel(); - - // Override local action methods in order to delegate execution to Channel - void addAction(int action, ActionHandler &client, int event) override; - void addAction(int action, ActionHandler *client, int event) override; - bool isEventAlreadyUsed(int event) override; - - virtual void addAction(int action, ActionHandler &client, Supla::Condition *condition); - virtual void addAction(int action, ActionHandler *client, Supla::Condition *condition); - - protected: - Channel channel; -}; - -}; - -#endif - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _channel_element_h +#define _channel_element_h + +#include "element.h" +#include "channel.h" +#include "local_action.h" +#include "action_handler.h" +#include "condition.h" + +namespace Supla { + +class Condition; + +class ChannelElement : public Element, public LocalAction { + public: + + Channel *getChannel(); + + // Override local action methods in order to delegate execution to Channel + void addAction(int action, ActionHandler &client, int event) override; + void addAction(int action, ActionHandler *client, int event) override; + bool isEventAlreadyUsed(int event) override; + + virtual void addAction(int action, ActionHandler &client, Supla::Condition *condition); + virtual void addAction(int action, ActionHandler *client, Supla::Condition *condition); + + protected: + Channel channel; +}; + +}; + +#endif + diff --git a/lib/SuplaDevice/src/supla/channel_extended.h b/lib/SuplaDevice/src/supla/channel_extended.h index 630a601f..101f31d2 100644 --- a/lib/SuplaDevice/src/supla/channel_extended.h +++ b/lib/SuplaDevice/src/supla/channel_extended.h @@ -1,34 +1,34 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _channel_extended_h -#define _channel_extended_h - -#include "channel.h" - -namespace Supla { -class ChannelExtended : public Channel { - public: - bool isExtended(); - TSuplaChannelExtendedValue *getExtValue(); - - protected: - TSuplaChannelExtendedValue extValue = {}; -}; - -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _channel_extended_h +#define _channel_extended_h + +#include "channel.h" + +namespace Supla { +class ChannelExtended : public Channel { + public: + bool isExtended(); + TSuplaChannelExtendedValue *getExtValue(); + + protected: + TSuplaChannelExtendedValue extValue = {}; +}; + +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/condition.cpp b/lib/SuplaDevice/src/supla/condition.cpp index 667225dd..0e34f796 100644 --- a/lib/SuplaDevice/src/supla/condition.cpp +++ b/lib/SuplaDevice/src/supla/condition.cpp @@ -1,131 +1,131 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "condition.h" -#include "events.h" -#include "element.h" - -Supla::Condition::Condition(double threshold, bool useAlternativeMeasurement) - : threshold(threshold), - useAlternativeMeasurement(useAlternativeMeasurement) -{ -} - -Supla::Condition::Condition(double threshold, Supla::ConditionGetter *getter) - : threshold(threshold), getter(getter) -{ -} - -Supla::Condition::~Condition() { -} - -void Supla::Condition::handleAction(int event, int action) { - if (event == Supla::ON_CHANGE || - event == Supla::ON_SECONDARY_CHANNEL_CHANGE) { - if (!source->getChannel()) { - return; - } - - int channelType = source->getChannel()->getChannelType(); - - // Read channel value - double value = 0; - bool isValid = true; - - if (getter) { - value = getter->getValue(source, isValid); - } else { - switch (channelType) { - case SUPLA_CHANNELTYPE_DISTANCESENSOR: - case SUPLA_CHANNELTYPE_THERMOMETER: - case SUPLA_CHANNELTYPE_WINDSENSOR: - case SUPLA_CHANNELTYPE_PRESSURESENSOR: - case SUPLA_CHANNELTYPE_RAINSENSOR: - case SUPLA_CHANNELTYPE_WEIGHTSENSOR: - value = source->getChannel()->getValueDouble(); - break; - case SUPLA_CHANNELTYPE_IMPULSE_COUNTER: - value = source->getChannel()->getValueInt64(); - break; - case SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR: - case SUPLA_CHANNELTYPE_HUMIDITYSENSOR: - value = useAlternativeMeasurement - ? source->getChannel()->getValueDoubleSecond() - : source->getChannel()->getValueDoubleFirst(); - break; - /* case SUPLA_CHANNELTYPE_ELECTRICITY_METER: */ - - default: - return; - } - - // Check channel value validity - switch (channelType) { - case SUPLA_CHANNELTYPE_DISTANCESENSOR: - case SUPLA_CHANNELTYPE_WINDSENSOR: - case SUPLA_CHANNELTYPE_PRESSURESENSOR: - case SUPLA_CHANNELTYPE_RAINSENSOR: - case SUPLA_CHANNELTYPE_WEIGHTSENSOR: - isValid = value >= 0; - break; - case SUPLA_CHANNELTYPE_THERMOMETER: - isValid = value >= -273; - break; - case SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR: - case SUPLA_CHANNELTYPE_HUMIDITYSENSOR: - isValid = useAlternativeMeasurement ? value >= 0 : value >= -273; - break; - } - } - if (checkConditionFor(value, isValid)) { - client->handleAction(event, action); - } - } -} - -// Condition objects will be deleted during ActionHandlerClient list cleanup -bool Supla::Condition::deleteClient() { - return true; -} - -bool Supla::Condition::checkConditionFor(double val, bool isValid) { - if (!alreadyFired && condition(val, isValid)) { - alreadyFired = true; - return true; - } - if (alreadyFired) { - if (!condition(val, isValid)) { - alreadyFired = false; - } - } - return false; -} - -void Supla::Condition::setSource(Supla::Element *src) { - source = src; -} - -void Supla::Condition::setClient(Supla::ActionHandler *clientPtr) { - client = clientPtr; -} - -void Supla::Condition::setSource(Supla::Element &src) { - setSource(&src); -} - -void Supla::Condition::setClient(Supla::ActionHandler &clientPtr) { - setClient(&clientPtr); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "condition.h" +#include "events.h" +#include "element.h" + +Supla::Condition::Condition(double threshold, bool useAlternativeMeasurement) + : threshold(threshold), + useAlternativeMeasurement(useAlternativeMeasurement) +{ +} + +Supla::Condition::Condition(double threshold, Supla::ConditionGetter *getter) + : threshold(threshold), getter(getter) +{ +} + +Supla::Condition::~Condition() { +} + +void Supla::Condition::handleAction(int event, int action) { + if (event == Supla::ON_CHANGE || + event == Supla::ON_SECONDARY_CHANNEL_CHANGE) { + if (!source->getChannel()) { + return; + } + + int channelType = source->getChannel()->getChannelType(); + + // Read channel value + double value = 0; + bool isValid = true; + + if (getter) { + value = getter->getValue(source, isValid); + } else { + switch (channelType) { + case SUPLA_CHANNELTYPE_DISTANCESENSOR: + case SUPLA_CHANNELTYPE_THERMOMETER: + case SUPLA_CHANNELTYPE_WINDSENSOR: + case SUPLA_CHANNELTYPE_PRESSURESENSOR: + case SUPLA_CHANNELTYPE_RAINSENSOR: + case SUPLA_CHANNELTYPE_WEIGHTSENSOR: + value = source->getChannel()->getValueDouble(); + break; + case SUPLA_CHANNELTYPE_IMPULSE_COUNTER: + value = source->getChannel()->getValueInt64(); + break; + case SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR: + case SUPLA_CHANNELTYPE_HUMIDITYSENSOR: + value = useAlternativeMeasurement + ? source->getChannel()->getValueDoubleSecond() + : source->getChannel()->getValueDoubleFirst(); + break; + /* case SUPLA_CHANNELTYPE_ELECTRICITY_METER: */ + + default: + return; + } + + // Check channel value validity + switch (channelType) { + case SUPLA_CHANNELTYPE_DISTANCESENSOR: + case SUPLA_CHANNELTYPE_WINDSENSOR: + case SUPLA_CHANNELTYPE_PRESSURESENSOR: + case SUPLA_CHANNELTYPE_RAINSENSOR: + case SUPLA_CHANNELTYPE_WEIGHTSENSOR: + isValid = value >= 0; + break; + case SUPLA_CHANNELTYPE_THERMOMETER: + isValid = value >= -273; + break; + case SUPLA_CHANNELTYPE_HUMIDITYANDTEMPSENSOR: + case SUPLA_CHANNELTYPE_HUMIDITYSENSOR: + isValid = useAlternativeMeasurement ? value >= 0 : value >= -273; + break; + } + } + if (checkConditionFor(value, isValid)) { + client->handleAction(event, action); + } + } +} + +// Condition objects will be deleted during ActionHandlerClient list cleanup +bool Supla::Condition::deleteClient() { + return true; +} + +bool Supla::Condition::checkConditionFor(double val, bool isValid) { + if (!alreadyFired && condition(val, isValid)) { + alreadyFired = true; + return true; + } + if (alreadyFired) { + if (!condition(val, isValid)) { + alreadyFired = false; + } + } + return false; +} + +void Supla::Condition::setSource(Supla::Element *src) { + source = src; +} + +void Supla::Condition::setClient(Supla::ActionHandler *clientPtr) { + client = clientPtr; +} + +void Supla::Condition::setSource(Supla::Element &src) { + setSource(&src); +} + +void Supla::Condition::setClient(Supla::ActionHandler &clientPtr) { + setClient(&clientPtr); +} diff --git a/lib/SuplaDevice/src/supla/condition.h b/lib/SuplaDevice/src/supla/condition.h index 60bce5a3..139ca9fa 100644 --- a/lib/SuplaDevice/src/supla/condition.h +++ b/lib/SuplaDevice/src/supla/condition.h @@ -1,74 +1,74 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _condition_h -#define _condition_h - -#include "action_handler.h" -#include "condition_getter.h" - -namespace Supla { - -class Element; - -class Condition : public ActionHandler { - public: - Condition(double threshold, bool useAlternativeMeasurement); - Condition(double threshold, ConditionGetter *getter); - - virtual ~Condition(); - void setSource(Element *src); - void setClient(ActionHandler *clientPtr); - void setSource(Element &src); - void setClient(ActionHandler &clientPtr); - - void handleAction(int event, int action); - bool deleteClient(); - virtual bool checkConditionFor(double val, bool isValid = true); - - protected: - virtual bool condition(double val, bool isValid = true) = 0; - - double threshold = 0; - bool useAlternativeMeasurement = false; - bool alreadyFired = false; - Supla::Element *source = nullptr; - Supla::ActionHandler *client = nullptr; - Supla::ConditionGetter *getter = nullptr; - -}; - -}; - -Supla::Condition *OnLess(double threshold, bool useAlternativeMeasurement = false); -Supla::Condition *OnLessEq(double threshold, bool useAlternativeMeasurement = false); -Supla::Condition *OnGreater(double threshold, bool useAlternativeMeasurement = false); -Supla::Condition *OnGreaterEq(double threshold, bool useAlternativeMeasurement = false); -Supla::Condition *OnBetween(double threshold1, double threshold2, bool useAlternativeMeasurement = false); -Supla::Condition *OnBetweenEq(double threshold1, double threshold2, bool useAlternativeMeasurement = false); -Supla::Condition *OnEqual(double threshold, bool useAlternativeMeasurement = false); -Supla::Condition *OnInvalid(bool useAlternativeMeasurement = false); - -Supla::Condition *OnLess(double threshold, Supla::ConditionGetter *); -Supla::Condition *OnLessEq(double threshold, Supla::ConditionGetter *); -Supla::Condition *OnGreater(double threshold, Supla::ConditionGetter *); -Supla::Condition *OnGreaterEq(double threshold, Supla::ConditionGetter *); -Supla::Condition *OnBetween(double threshold1, double threshold2, Supla::ConditionGetter *); -Supla::Condition *OnBetweenEq(double threshold1, double threshold2, Supla::ConditionGetter *); -Supla::Condition *OnEqual(double threshold, Supla::ConditionGetter *); -Supla::Condition *OnInvalid(Supla::ConditionGetter *); - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _condition_h +#define _condition_h + +#include "action_handler.h" +#include "condition_getter.h" + +namespace Supla { + +class Element; + +class Condition : public ActionHandler { + public: + Condition(double threshold, bool useAlternativeMeasurement); + Condition(double threshold, ConditionGetter *getter); + + virtual ~Condition(); + void setSource(Element *src); + void setClient(ActionHandler *clientPtr); + void setSource(Element &src); + void setClient(ActionHandler &clientPtr); + + void handleAction(int event, int action); + bool deleteClient(); + virtual bool checkConditionFor(double val, bool isValid = true); + + protected: + virtual bool condition(double val, bool isValid = true) = 0; + + double threshold = 0; + bool useAlternativeMeasurement = false; + bool alreadyFired = false; + Supla::Element *source = nullptr; + Supla::ActionHandler *client = nullptr; + Supla::ConditionGetter *getter = nullptr; + +}; + +}; + +Supla::Condition *OnLess(double threshold, bool useAlternativeMeasurement = false); +Supla::Condition *OnLessEq(double threshold, bool useAlternativeMeasurement = false); +Supla::Condition *OnGreater(double threshold, bool useAlternativeMeasurement = false); +Supla::Condition *OnGreaterEq(double threshold, bool useAlternativeMeasurement = false); +Supla::Condition *OnBetween(double threshold1, double threshold2, bool useAlternativeMeasurement = false); +Supla::Condition *OnBetweenEq(double threshold1, double threshold2, bool useAlternativeMeasurement = false); +Supla::Condition *OnEqual(double threshold, bool useAlternativeMeasurement = false); +Supla::Condition *OnInvalid(bool useAlternativeMeasurement = false); + +Supla::Condition *OnLess(double threshold, Supla::ConditionGetter *); +Supla::Condition *OnLessEq(double threshold, Supla::ConditionGetter *); +Supla::Condition *OnGreater(double threshold, Supla::ConditionGetter *); +Supla::Condition *OnGreaterEq(double threshold, Supla::ConditionGetter *); +Supla::Condition *OnBetween(double threshold1, double threshold2, Supla::ConditionGetter *); +Supla::Condition *OnBetweenEq(double threshold1, double threshold2, Supla::ConditionGetter *); +Supla::Condition *OnEqual(double threshold, Supla::ConditionGetter *); +Supla::Condition *OnInvalid(Supla::ConditionGetter *); + +#endif diff --git a/lib/SuplaDevice/src/supla/condition_getter.cpp b/lib/SuplaDevice/src/supla/condition_getter.cpp index c8e0129f..b2193a72 100644 --- a/lib/SuplaDevice/src/supla/condition_getter.cpp +++ b/lib/SuplaDevice/src/supla/condition_getter.cpp @@ -1,290 +1,290 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "condition_getter.h" -#include "element.h" - -namespace Supla { - -TElectricityMeter_Measurement *ConditionGetter::getMeasurement( - Supla::Element *element, _supla_int_t &measuredValues) { - if (!element || !element->getChannel() || - !element->getChannel()->getExtValue() || - element->getChannel()->getChannelType() != - SUPLA_CHANNELTYPE_ELECTRICITY_METER) { - return nullptr; - } - - TSuplaChannelExtendedValue *extValue = element->getChannel()->getExtValue(); - if (extValue->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2) { - return nullptr; - } - - TElectricityMeter_ExtendedValue_V2 *emValue = - reinterpret_cast(extValue->value); - - if (emValue->m_count < 1) { - return nullptr; - } - - measuredValues = emValue->measured_values; - return &(emValue->m[0]); -} - -class VoltageGetter : public ConditionGetter { - public: - VoltageGetter(int8_t phase) : phase(phase) {} - - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - if (phase < 0 || phase >= 3 /* MAX_PHASES */) { - return 0; - } - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_VOLTAGE) { - isValid = true; - return measurement->voltage[phase] / 100.0; - } - } - - return 0; - } - protected: - int8_t phase = 0; -}; - -class CurrentGetter : public ConditionGetter { - public: - CurrentGetter(int8_t phase) : phase(phase) {} - - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - if (phase < 0 || phase >= 3 /* MAX_PHASES */) { - return 0; - } - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_CURRENT) { - isValid = true; - return measurement->current[phase] / 1000.0; - } - if (measuredValues & EM_VAR_CURRENT_OVER_65A) { - isValid = true; - return measurement->current[phase] / 100.0; - } - } - - return 0; - } - protected: - int8_t phase = 0; -}; - -class TotalCurrentGetter : public ConditionGetter { - public: - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - double totalCurrent = - (measurement->current[0] + measurement->current[1] + measurement->current[2]); - if (measuredValues & EM_VAR_CURRENT) { - isValid = true; - return totalCurrent / 1000.0; - } - if (measuredValues & EM_VAR_CURRENT_OVER_65A) { - isValid = true; - return totalCurrent / 100.0; - } - } - - return 0; - } -}; - -class PowerActiveWGetter : public ConditionGetter { - public: - PowerActiveWGetter(int8_t phase) : phase(phase) {} - - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - if (phase < 0 || phase >= 3 /* MAX_PHASES */) { - return 0; - } - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_ACTIVE) { - isValid = true; - return measurement->power_active[phase] / 100.0; - } - } - - return 0; - } - protected: - int8_t phase = 0; -}; - -class TotalPowerActiveWGetter : public ConditionGetter { - public: - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_ACTIVE) { - double totalPower = - measurement->power_active[0] + measurement->power_active[1] + - measurement->power_active[2]; - isValid = true; - return totalPower / 100.0; - } - } - - return 0; - } -}; - -class PowerApparentVAGetter : public ConditionGetter { - public: - PowerApparentVAGetter(int8_t phase) : phase(phase) {} - - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - if (phase < 0 || phase >= 3 /* MAX_PHASES */) { - return 0; - } - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_APPARENT) { - isValid = true; - return measurement->power_apparent[phase] / 100.0; - } - } - - return 0; - } - protected: - int8_t phase = 0; -}; - -class TotalPowerApparentVAGetter : public ConditionGetter { - public: - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_APPARENT) { - double totalPower = - measurement->power_apparent[0] + measurement->power_apparent[1] + - measurement->power_apparent[2]; - isValid = true; - return totalPower / 100.0; - } - } - - return 0; - } -}; - -class PowerReactiveVarGetter : public ConditionGetter { - public: - PowerReactiveVarGetter(int8_t phase) : phase(phase) {} - - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - if (phase < 0 || phase >= 3 /* MAX_PHASES */) { - return 0; - } - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_REACTIVE) { - isValid = true; - return measurement->power_reactive[phase] / 100.0; - } - } - - return 0; - } - protected: - int8_t phase = 0; -}; - -class TotalPowerReactiveVarGetter : public ConditionGetter { - public: - double getValue(Supla::Element *element, bool &isValid) override { - isValid = false; - - _supla_int_t measuredValues = 0; - if (auto measurement = getMeasurement(element, measuredValues)) { - if (measuredValues & EM_VAR_POWER_REACTIVE) { - double totalPower = - measurement->power_reactive[0] + measurement->power_reactive[1] + - measurement->power_reactive[2]; - isValid = true; - return totalPower / 100.0; - } - } - - return 0; - } -}; - -}; - -Supla::ConditionGetter *EmVoltage(int8_t phase) { - return new Supla::VoltageGetter(phase); -} - -Supla::ConditionGetter *EmCurrent(int8_t phase) { - return new Supla::CurrentGetter(phase); -} - -Supla::ConditionGetter *EmTotalCurrent() { - return new Supla::TotalCurrentGetter(); -} - -Supla::ConditionGetter *EmPowerActiveW(int8_t phase) { - return new Supla::PowerActiveWGetter(phase); -} - -Supla::ConditionGetter *EmTotalPowerActiveW() { - return new Supla::TotalPowerActiveWGetter(); -} - -Supla::ConditionGetter *EmPowerApparentVA(int8_t phase) { - return new Supla::PowerApparentVAGetter(phase); -} - -Supla::ConditionGetter *EmTotalPowerApparentVA() { - return new Supla::TotalPowerApparentVAGetter(); -} - -Supla::ConditionGetter *EmPowerReactiveVar(int8_t phase) { - return new Supla::PowerReactiveVarGetter(phase); -} - -Supla::ConditionGetter *EmTotalPowerReactiveVar() { - return new Supla::TotalPowerReactiveVarGetter(); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "condition_getter.h" +#include "element.h" + +namespace Supla { + +TElectricityMeter_Measurement *ConditionGetter::getMeasurement( + Supla::Element *element, _supla_int_t &measuredValues) { + if (!element || !element->getChannel() || + !element->getChannel()->getExtValue() || + element->getChannel()->getChannelType() != + SUPLA_CHANNELTYPE_ELECTRICITY_METER) { + return nullptr; + } + + TSuplaChannelExtendedValue *extValue = element->getChannel()->getExtValue(); + if (extValue->type != EV_TYPE_ELECTRICITY_METER_MEASUREMENT_V2) { + return nullptr; + } + + TElectricityMeter_ExtendedValue_V2 *emValue = + reinterpret_cast(extValue->value); + + if (emValue->m_count < 1) { + return nullptr; + } + + measuredValues = emValue->measured_values; + return &(emValue->m[0]); +} + +class VoltageGetter : public ConditionGetter { + public: + VoltageGetter(int8_t phase) : phase(phase) {} + + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + if (phase < 0 || phase >= 3 /* MAX_PHASES */) { + return 0; + } + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_VOLTAGE) { + isValid = true; + return measurement->voltage[phase] / 100.0; + } + } + + return 0; + } + protected: + int8_t phase = 0; +}; + +class CurrentGetter : public ConditionGetter { + public: + CurrentGetter(int8_t phase) : phase(phase) {} + + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + if (phase < 0 || phase >= 3 /* MAX_PHASES */) { + return 0; + } + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_CURRENT) { + isValid = true; + return measurement->current[phase] / 1000.0; + } + if (measuredValues & EM_VAR_CURRENT_OVER_65A) { + isValid = true; + return measurement->current[phase] / 100.0; + } + } + + return 0; + } + protected: + int8_t phase = 0; +}; + +class TotalCurrentGetter : public ConditionGetter { + public: + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + double totalCurrent = + (measurement->current[0] + measurement->current[1] + measurement->current[2]); + if (measuredValues & EM_VAR_CURRENT) { + isValid = true; + return totalCurrent / 1000.0; + } + if (measuredValues & EM_VAR_CURRENT_OVER_65A) { + isValid = true; + return totalCurrent / 100.0; + } + } + + return 0; + } +}; + +class PowerActiveWGetter : public ConditionGetter { + public: + PowerActiveWGetter(int8_t phase) : phase(phase) {} + + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + if (phase < 0 || phase >= 3 /* MAX_PHASES */) { + return 0; + } + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_ACTIVE) { + isValid = true; + return measurement->power_active[phase] / 100.0; + } + } + + return 0; + } + protected: + int8_t phase = 0; +}; + +class TotalPowerActiveWGetter : public ConditionGetter { + public: + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_ACTIVE) { + double totalPower = + measurement->power_active[0] + measurement->power_active[1] + + measurement->power_active[2]; + isValid = true; + return totalPower / 100.0; + } + } + + return 0; + } +}; + +class PowerApparentVAGetter : public ConditionGetter { + public: + PowerApparentVAGetter(int8_t phase) : phase(phase) {} + + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + if (phase < 0 || phase >= 3 /* MAX_PHASES */) { + return 0; + } + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_APPARENT) { + isValid = true; + return measurement->power_apparent[phase] / 100.0; + } + } + + return 0; + } + protected: + int8_t phase = 0; +}; + +class TotalPowerApparentVAGetter : public ConditionGetter { + public: + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_APPARENT) { + double totalPower = + measurement->power_apparent[0] + measurement->power_apparent[1] + + measurement->power_apparent[2]; + isValid = true; + return totalPower / 100.0; + } + } + + return 0; + } +}; + +class PowerReactiveVarGetter : public ConditionGetter { + public: + PowerReactiveVarGetter(int8_t phase) : phase(phase) {} + + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + if (phase < 0 || phase >= 3 /* MAX_PHASES */) { + return 0; + } + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_REACTIVE) { + isValid = true; + return measurement->power_reactive[phase] / 100.0; + } + } + + return 0; + } + protected: + int8_t phase = 0; +}; + +class TotalPowerReactiveVarGetter : public ConditionGetter { + public: + double getValue(Supla::Element *element, bool &isValid) override { + isValid = false; + + _supla_int_t measuredValues = 0; + if (auto measurement = getMeasurement(element, measuredValues)) { + if (measuredValues & EM_VAR_POWER_REACTIVE) { + double totalPower = + measurement->power_reactive[0] + measurement->power_reactive[1] + + measurement->power_reactive[2]; + isValid = true; + return totalPower / 100.0; + } + } + + return 0; + } +}; + +}; + +Supla::ConditionGetter *EmVoltage(int8_t phase) { + return new Supla::VoltageGetter(phase); +} + +Supla::ConditionGetter *EmCurrent(int8_t phase) { + return new Supla::CurrentGetter(phase); +} + +Supla::ConditionGetter *EmTotalCurrent() { + return new Supla::TotalCurrentGetter(); +} + +Supla::ConditionGetter *EmPowerActiveW(int8_t phase) { + return new Supla::PowerActiveWGetter(phase); +} + +Supla::ConditionGetter *EmTotalPowerActiveW() { + return new Supla::TotalPowerActiveWGetter(); +} + +Supla::ConditionGetter *EmPowerApparentVA(int8_t phase) { + return new Supla::PowerApparentVAGetter(phase); +} + +Supla::ConditionGetter *EmTotalPowerApparentVA() { + return new Supla::TotalPowerApparentVAGetter(); +} + +Supla::ConditionGetter *EmPowerReactiveVar(int8_t phase) { + return new Supla::PowerReactiveVarGetter(phase); +} + +Supla::ConditionGetter *EmTotalPowerReactiveVar() { + return new Supla::TotalPowerReactiveVarGetter(); +} diff --git a/lib/SuplaDevice/src/supla/condition_getter.h b/lib/SuplaDevice/src/supla/condition_getter.h index 40b4578f..42d48697 100644 --- a/lib/SuplaDevice/src/supla/condition_getter.h +++ b/lib/SuplaDevice/src/supla/condition_getter.h @@ -1,48 +1,48 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _condition_getter_h -#define _condition_getter_h - -#include -#include - -namespace Supla { - -class Element; - -class ConditionGetter { - public: - virtual double getValue(Supla::Element *element, bool &isValid) = 0; - protected: - TElectricityMeter_Measurement *getMeasurement(Supla::Element *element, - _supla_int_t &measuredValues); -}; - - -}; // namespace Supla - -Supla::ConditionGetter *EmVoltage(int8_t phase = 0); -Supla::ConditionGetter *EmCurrent(int8_t phase = 0); -Supla::ConditionGetter *EmTotalCurrent(); -Supla::ConditionGetter *EmPowerActiveW(int8_t phase = 0); -Supla::ConditionGetter *EmTotalPowerActiveW(); -Supla::ConditionGetter *EmPowerApparentVA(int8_t phase = 0); -Supla::ConditionGetter *EmTotalPowerApparentVA(); -Supla::ConditionGetter *EmPowerReactiveVar(int8_t phase = 0); -Supla::ConditionGetter *EmTotalPowerReactiveVar(); - -#endif /*_condition_getter_h*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _condition_getter_h +#define _condition_getter_h + +#include +#include + +namespace Supla { + +class Element; + +class ConditionGetter { + public: + virtual double getValue(Supla::Element *element, bool &isValid) = 0; + protected: + TElectricityMeter_Measurement *getMeasurement(Supla::Element *element, + _supla_int_t &measuredValues); +}; + + +}; // namespace Supla + +Supla::ConditionGetter *EmVoltage(int8_t phase = 0); +Supla::ConditionGetter *EmCurrent(int8_t phase = 0); +Supla::ConditionGetter *EmTotalCurrent(); +Supla::ConditionGetter *EmPowerActiveW(int8_t phase = 0); +Supla::ConditionGetter *EmTotalPowerActiveW(); +Supla::ConditionGetter *EmPowerApparentVA(int8_t phase = 0); +Supla::ConditionGetter *EmTotalPowerApparentVA(); +Supla::ConditionGetter *EmPowerReactiveVar(int8_t phase = 0); +Supla::ConditionGetter *EmTotalPowerReactiveVar(); + +#endif /*_condition_getter_h*/ diff --git a/lib/SuplaDevice/src/supla/conditions/on_between.cpp b/lib/SuplaDevice/src/supla/conditions/on_between.cpp index 264d98fe..83e2f0fc 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_between.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_between.cpp @@ -1,47 +1,47 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnBetweenCond : public Supla::Condition { - public: - OnBetweenCond(double threshold1, double threshold2, bool useAlternativeMeasurement) - : Supla::Condition(threshold1, useAlternativeMeasurement), threshold2(threshold2) { - } - - OnBetweenCond(double threshold1, double threshold2, Supla::ConditionGetter *getter) - : Supla::Condition(threshold1, getter), threshold2(threshold2) { - } - - bool condition(double val, bool isValid) { - if (isValid) { - return val > threshold && val < threshold2; - } - return false; - } - - double threshold2; -}; - - -Supla::Condition *OnBetween(double threshold1, double threshold2, bool useAlternativeMeasurement) { - return new OnBetweenCond(threshold1, threshold2, useAlternativeMeasurement); -} - -Supla::Condition *OnBetween(double threshold1, double threshold2, Supla::ConditionGetter *getter) { - return new OnBetweenCond(threshold1, threshold2, getter); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnBetweenCond : public Supla::Condition { + public: + OnBetweenCond(double threshold1, double threshold2, bool useAlternativeMeasurement) + : Supla::Condition(threshold1, useAlternativeMeasurement), threshold2(threshold2) { + } + + OnBetweenCond(double threshold1, double threshold2, Supla::ConditionGetter *getter) + : Supla::Condition(threshold1, getter), threshold2(threshold2) { + } + + bool condition(double val, bool isValid) { + if (isValid) { + return val > threshold && val < threshold2; + } + return false; + } + + double threshold2; +}; + + +Supla::Condition *OnBetween(double threshold1, double threshold2, bool useAlternativeMeasurement) { + return new OnBetweenCond(threshold1, threshold2, useAlternativeMeasurement); +} + +Supla::Condition *OnBetween(double threshold1, double threshold2, Supla::ConditionGetter *getter) { + return new OnBetweenCond(threshold1, threshold2, getter); +} + diff --git a/lib/SuplaDevice/src/supla/conditions/on_between_eq.cpp b/lib/SuplaDevice/src/supla/conditions/on_between_eq.cpp index a9adb631..a0c8edf5 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_between_eq.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_between_eq.cpp @@ -1,47 +1,47 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnBetweenEqCond : public Supla::Condition { - public: - OnBetweenEqCond(double threshold1, double threshold2, bool useAlternativeMeasurement) - : Supla::Condition(threshold1, useAlternativeMeasurement), threshold2(threshold2) { - } - - OnBetweenEqCond(double threshold1, double threshold2, Supla::ConditionGetter *getter) - : Supla::Condition(threshold1, getter), threshold2(threshold2) { - } - - bool condition(double val, bool isValid) { - if (isValid) { - return val >= threshold && val <= threshold2; - } - return false; - } - - double threshold2; -}; - - -Supla::Condition *OnBetweenEq(double threshold1, double threshold2, bool useAlternativeMeasurement) { - return new OnBetweenEqCond(threshold1, threshold2, useAlternativeMeasurement); -} - -Supla::Condition *OnBetweenEq(double threshold1, double threshold2, Supla::ConditionGetter *getter) { - return new OnBetweenEqCond(threshold1, threshold2, getter); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnBetweenEqCond : public Supla::Condition { + public: + OnBetweenEqCond(double threshold1, double threshold2, bool useAlternativeMeasurement) + : Supla::Condition(threshold1, useAlternativeMeasurement), threshold2(threshold2) { + } + + OnBetweenEqCond(double threshold1, double threshold2, Supla::ConditionGetter *getter) + : Supla::Condition(threshold1, getter), threshold2(threshold2) { + } + + bool condition(double val, bool isValid) { + if (isValid) { + return val >= threshold && val <= threshold2; + } + return false; + } + + double threshold2; +}; + + +Supla::Condition *OnBetweenEq(double threshold1, double threshold2, bool useAlternativeMeasurement) { + return new OnBetweenEqCond(threshold1, threshold2, useAlternativeMeasurement); +} + +Supla::Condition *OnBetweenEq(double threshold1, double threshold2, Supla::ConditionGetter *getter) { + return new OnBetweenEqCond(threshold1, threshold2, getter); +} + diff --git a/lib/SuplaDevice/src/supla/conditions/on_equal.cpp b/lib/SuplaDevice/src/supla/conditions/on_equal.cpp index 28b359f4..1578ab1e 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_equal.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_equal.cpp @@ -1,39 +1,39 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnEqualCond : public Supla::Condition { - public: - using Supla::Condition::Condition; - - bool condition(double val, bool isValid) { - if (isValid) { - return val == threshold; - } - return false; - } -}; - - -Supla::Condition *OnEqual(double threshold, bool useAlternativeMeasurement) { - return new OnEqualCond(threshold, useAlternativeMeasurement); -} - -Supla::Condition *OnEqual(double threshold, Supla::ConditionGetter *getter) { - return new OnEqualCond(threshold, getter); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnEqualCond : public Supla::Condition { + public: + using Supla::Condition::Condition; + + bool condition(double val, bool isValid) { + if (isValid) { + return val == threshold; + } + return false; + } +}; + + +Supla::Condition *OnEqual(double threshold, bool useAlternativeMeasurement) { + return new OnEqualCond(threshold, useAlternativeMeasurement); +} + +Supla::Condition *OnEqual(double threshold, Supla::ConditionGetter *getter) { + return new OnEqualCond(threshold, getter); +} + diff --git a/lib/SuplaDevice/src/supla/conditions/on_greater.cpp b/lib/SuplaDevice/src/supla/conditions/on_greater.cpp index ba25fe00..a3dbb7a4 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_greater.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_greater.cpp @@ -1,40 +1,40 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnGreaterCond : public Supla::Condition { - public: - using Supla::Condition::Condition; - - bool condition(double val, bool isValid) { - if (isValid) { - return val > threshold; - } - return false; - } -}; - - -Supla::Condition *OnGreater(double threshold, bool useAlternativeMeasurement) { - return new OnGreaterCond(threshold, useAlternativeMeasurement); -} - -Supla::Condition *OnGreater(double threshold, Supla::ConditionGetter *getter) { - return new OnGreaterCond(threshold, getter); -} - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnGreaterCond : public Supla::Condition { + public: + using Supla::Condition::Condition; + + bool condition(double val, bool isValid) { + if (isValid) { + return val > threshold; + } + return false; + } +}; + + +Supla::Condition *OnGreater(double threshold, bool useAlternativeMeasurement) { + return new OnGreaterCond(threshold, useAlternativeMeasurement); +} + +Supla::Condition *OnGreater(double threshold, Supla::ConditionGetter *getter) { + return new OnGreaterCond(threshold, getter); +} + + diff --git a/lib/SuplaDevice/src/supla/conditions/on_greater_eq.cpp b/lib/SuplaDevice/src/supla/conditions/on_greater_eq.cpp index d3c50ea5..e89e4abd 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_greater_eq.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_greater_eq.cpp @@ -1,38 +1,38 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnGreaterEqCond : public Supla::Condition { - public: - using Supla::Condition::Condition; - - bool condition(double val, bool isValid) { - if (isValid) { - return val >= threshold; - } - return false; - } -}; - - -Supla::Condition *OnGreaterEq(double threshold, bool useAlternativeMeasurement) { - return new OnGreaterEqCond(threshold, useAlternativeMeasurement); -} - -Supla::Condition *OnGreaterEq(double threshold, Supla::ConditionGetter *getter) { - return new OnGreaterEqCond(threshold, getter); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnGreaterEqCond : public Supla::Condition { + public: + using Supla::Condition::Condition; + + bool condition(double val, bool isValid) { + if (isValid) { + return val >= threshold; + } + return false; + } +}; + + +Supla::Condition *OnGreaterEq(double threshold, bool useAlternativeMeasurement) { + return new OnGreaterEqCond(threshold, useAlternativeMeasurement); +} + +Supla::Condition *OnGreaterEq(double threshold, Supla::ConditionGetter *getter) { + return new OnGreaterEqCond(threshold, getter); +} diff --git a/lib/SuplaDevice/src/supla/conditions/on_invalid.cpp b/lib/SuplaDevice/src/supla/conditions/on_invalid.cpp index bd7f1a88..8f97cfab 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_invalid.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_invalid.cpp @@ -1,43 +1,43 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnInvalidCond : public Supla::Condition { - public: - OnInvalidCond(bool useAlternativeMeasurement) - : Supla::Condition(0, useAlternativeMeasurement) { - } - - OnInvalidCond(Supla::ConditionGetter *getter) - : Supla::Condition(0, getter) { - } - - bool condition(double val, bool isValid) { - (void)(val); - return !isValid; - } - -}; - - -Supla::Condition *OnInvalid(bool useAlternativeMeasurement) { - return new OnInvalidCond(useAlternativeMeasurement); -} - -Supla::Condition *OnInvalid(Supla::ConditionGetter *getter) { - return new OnInvalidCond(getter); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnInvalidCond : public Supla::Condition { + public: + OnInvalidCond(bool useAlternativeMeasurement) + : Supla::Condition(0, useAlternativeMeasurement) { + } + + OnInvalidCond(Supla::ConditionGetter *getter) + : Supla::Condition(0, getter) { + } + + bool condition(double val, bool isValid) { + (void)(val); + return !isValid; + } + +}; + + +Supla::Condition *OnInvalid(bool useAlternativeMeasurement) { + return new OnInvalidCond(useAlternativeMeasurement); +} + +Supla::Condition *OnInvalid(Supla::ConditionGetter *getter) { + return new OnInvalidCond(getter); +} diff --git a/lib/SuplaDevice/src/supla/conditions/on_less.cpp b/lib/SuplaDevice/src/supla/conditions/on_less.cpp index 85045cef..5444dabe 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_less.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_less.cpp @@ -1,40 +1,40 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnLessCond : public Supla::Condition { - public: - using Supla::Condition::Condition; - - bool condition(double val, bool isValid) { - if (isValid) { - return val < threshold; - } - return false; - } -}; - - -Supla::Condition *OnLess(double threshold, bool useAlternativeMeasurement) { - return new OnLessCond(threshold, useAlternativeMeasurement); -} - -Supla::Condition *OnLess(double threshold, Supla::ConditionGetter *getter) { - return new OnLessCond(threshold, getter); -} - - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnLessCond : public Supla::Condition { + public: + using Supla::Condition::Condition; + + bool condition(double val, bool isValid) { + if (isValid) { + return val < threshold; + } + return false; + } +}; + + +Supla::Condition *OnLess(double threshold, bool useAlternativeMeasurement) { + return new OnLessCond(threshold, useAlternativeMeasurement); +} + +Supla::Condition *OnLess(double threshold, Supla::ConditionGetter *getter) { + return new OnLessCond(threshold, getter); +} + + diff --git a/lib/SuplaDevice/src/supla/conditions/on_less_eq.cpp b/lib/SuplaDevice/src/supla/conditions/on_less_eq.cpp index db6ba23f..b8067dc7 100644 --- a/lib/SuplaDevice/src/supla/conditions/on_less_eq.cpp +++ b/lib/SuplaDevice/src/supla/conditions/on_less_eq.cpp @@ -1,39 +1,39 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "../condition.h" - -class OnLessEqCond : public Supla::Condition { - public: - using Supla::Condition::Condition; - - bool condition(double val, bool isValid) { - if (isValid) { - return val <= threshold; - } - return false; - } -}; - - -Supla::Condition *OnLessEq(double threshold, bool useAlternativeMeasurement) { - return new OnLessEqCond(threshold, useAlternativeMeasurement); -} - -Supla::Condition *OnLessEq(double threshold, Supla::ConditionGetter *getter) { - return new OnLessEqCond(threshold, getter); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "../condition.h" + +class OnLessEqCond : public Supla::Condition { + public: + using Supla::Condition::Condition; + + bool condition(double val, bool isValid) { + if (isValid) { + return val <= threshold; + } + return false; + } +}; + + +Supla::Condition *OnLessEq(double threshold, bool useAlternativeMeasurement) { + return new OnLessEqCond(threshold, useAlternativeMeasurement); +} + +Supla::Condition *OnLessEq(double threshold, Supla::ConditionGetter *getter) { + return new OnLessEqCond(threshold, getter); +} + diff --git a/lib/SuplaDevice/src/supla/control/action_trigger.cpp b/lib/SuplaDevice/src/supla/control/action_trigger.cpp index 30ea1d3f..09ebffaf 100644 --- a/lib/SuplaDevice/src/supla/control/action_trigger.cpp +++ b/lib/SuplaDevice/src/supla/control/action_trigger.cpp @@ -1,261 +1,261 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "action_trigger.h" - -Supla::Control::ActionTrigger::ActionTrigger() { - channel.setType(SUPLA_CHANNELTYPE_ACTIONTRIGGER); - channel.setDefault(SUPLA_CHANNELFNC_ACTIONTRIGGER); -} - -Supla::Control::ActionTrigger::~ActionTrigger() {} - -void Supla::Control::ActionTrigger::attach(Supla::Control::Button *button) { - attachedButton = button; -} - -void Supla::Control::ActionTrigger::attach(Supla::Control::Button &button) { - attach(&button); -} - -void Supla::Control::ActionTrigger::handleAction(int event, int action) { - (void)(event); - uint32_t actionCap = getActionTriggerCap(action); - - if (actionCap & activeActionsFromServer) { - channel.pushAction(actionCap); - } -} - -Supla::Channel *Supla::Control::ActionTrigger::getChannel() { - return &channel; -} - -void Supla::Control::ActionTrigger::activateAction(int action) { - channel.activateAction(getActionTriggerCap(action)); -} - -int Supla::Control::ActionTrigger::getActionTriggerCap(int action) { - switch (action) { - case SEND_AT_TURN_ON: { - return SUPLA_ACTION_CAP_TURN_ON; - } - case SEND_AT_TURN_OFF: { - return SUPLA_ACTION_CAP_TURN_OFF; - } - case SEND_AT_TOGGLE_x1: { - return SUPLA_ACTION_CAP_TOGGLE_x1; - } - case SEND_AT_TOGGLE_x2: { - return SUPLA_ACTION_CAP_TOGGLE_x2; - } - case SEND_AT_TOGGLE_x3: { - return SUPLA_ACTION_CAP_TOGGLE_x3; - } - case SEND_AT_TOGGLE_x4: { - return SUPLA_ACTION_CAP_TOGGLE_x4; - } - case SEND_AT_TOGGLE_x5: { - return SUPLA_ACTION_CAP_TOGGLE_x5; - } - case SEND_AT_HOLD: { - return SUPLA_ACTION_CAP_HOLD; - } - case SEND_AT_SHORT_PRESS_x1: { - return SUPLA_ACTION_CAP_SHORT_PRESS_x1; - } - case SEND_AT_SHORT_PRESS_x2: { - return SUPLA_ACTION_CAP_SHORT_PRESS_x2; - } - case SEND_AT_SHORT_PRESS_x3: { - return SUPLA_ACTION_CAP_SHORT_PRESS_x3; - } - case SEND_AT_SHORT_PRESS_x4: { - return SUPLA_ACTION_CAP_SHORT_PRESS_x4; - } - case SEND_AT_SHORT_PRESS_x5: { - return SUPLA_ACTION_CAP_SHORT_PRESS_x5; - } - } - return 0; -} - -int Supla::Control::ActionTrigger::actionTriggerCapToButtonEvent( - uint32_t actionCap) { - switch (actionCap) { - case SUPLA_ACTION_CAP_TURN_ON: { - return Supla::ON_PRESS; - } - case SUPLA_ACTION_CAP_TURN_OFF: { - return Supla::ON_RELEASE; - } - case SUPLA_ACTION_CAP_HOLD: { - return Supla::ON_HOLD; - } - case SUPLA_ACTION_CAP_SHORT_PRESS_x1: - case SUPLA_ACTION_CAP_TOGGLE_x1: { - return Supla::ON_CLICK_1; - } - case SUPLA_ACTION_CAP_SHORT_PRESS_x2: - case SUPLA_ACTION_CAP_TOGGLE_x2: { - return Supla::ON_CLICK_2; - } - case SUPLA_ACTION_CAP_SHORT_PRESS_x3: - case SUPLA_ACTION_CAP_TOGGLE_x3: { - return Supla::ON_CLICK_3; - } - case SUPLA_ACTION_CAP_SHORT_PRESS_x4: - case SUPLA_ACTION_CAP_TOGGLE_x4: { - return Supla::ON_CLICK_4; - } - case SUPLA_ACTION_CAP_SHORT_PRESS_x5: - case SUPLA_ACTION_CAP_TOGGLE_x5: { - return Supla::ON_CLICK_5; - } - } - return 0; -} - - -void Supla::Control::ActionTrigger::onRegistered() { - // cleanup actions to be send - while (channel.popAction()); - - channel.requestChannelConfig(); - -} - -void Supla::Control::ActionTrigger::handleChannelConfig( - TSD_ChannelConfig *result) { - if (result->ConfigType == 0 && - result->ConfigSize == sizeof(TSD_ChannelConfig_ActionTrigger)) { - TSD_ChannelConfig_ActionTrigger *config = - reinterpret_cast(result->Config); - activeActionsFromServer = config->ActiveActions; - Serial.print(F("AT[")); - Serial.print(channel.getChannelNumber()); - Serial.print(F("] received config with active actions: ")); - Serial.println(activeActionsFromServer); - uint32_t actionsToDisable = activeActionsFromServer & disablesLocalOperation; - if (attachedButton) { - for (int i = 0; i < 32; i++) { - uint32_t actionCap = (1 << i); - if (actionsToDisable & actionCap) { - int eventToDisable = actionTriggerCapToButtonEvent(actionCap); - attachedButton->disableOtherClients(this, eventToDisable); - } else if (disablesLocalOperation & actionCap) { - int eventToEnable = actionTriggerCapToButtonEvent(actionCap); - attachedButton->enableOtherClients(this, eventToEnable); - } - } - } - } else { - Serial.println(F("Invalid format of channel config received for AT")); - } -} - -void Supla::Control::ActionTrigger::setRelatedChannel(Element *element) { - if (element && element->getChannel()) { - setRelatedChannel(element->getChannel()); - } -} - -void Supla::Control::ActionTrigger::setRelatedChannel(Element &element) { - setRelatedChannel(&element); -} - -void Supla::Control::ActionTrigger::setRelatedChannel(Channel *relatedChannel) { - if (relatedChannel) { - channel.setRelatedChannel(relatedChannel->getChannelNumber()); - } -} - -void Supla::Control::ActionTrigger::setRelatedChannel(Channel &relatedChannel) { - setRelatedChannel(&relatedChannel); -} - -void Supla::Control::ActionTrigger::onInit() { - if (attachedButton && attachedButton->isBistable()) { - if (attachedButton->isEventAlreadyUsed(Supla::ON_PRESS)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TURN_ON; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_RELEASE)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TURN_OFF; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_1)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x1; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_2)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x2; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_3)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x3; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_4)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x4; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_5)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x5; - } - - attachedButton->addAction(Supla::SEND_AT_TURN_ON, this, Supla::ON_PRESS); - attachedButton->addAction(Supla::SEND_AT_TURN_OFF, this, Supla::ON_RELEASE); - attachedButton->addAction( - Supla::SEND_AT_TOGGLE_x1, this, Supla::ON_CLICK_1); - attachedButton->addAction( - Supla::SEND_AT_TOGGLE_x2, this, Supla::ON_CLICK_2); - attachedButton->addAction( - Supla::SEND_AT_TOGGLE_x3, this, Supla::ON_CLICK_3); - attachedButton->addAction( - Supla::SEND_AT_TOGGLE_x4, this, Supla::ON_CLICK_4); - attachedButton->addAction( - Supla::SEND_AT_TOGGLE_x5, this, Supla::ON_CLICK_5); - } - if (attachedButton && !attachedButton->isBistable()) { - if (attachedButton->isEventAlreadyUsed(Supla::ON_HOLD)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_HOLD; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_1)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x1; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_2)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x2; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_3)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x3; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_4)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x4; - } - if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_5)) { - disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x5; - } - - attachedButton->addAction(Supla::SEND_AT_HOLD, this, Supla::ON_HOLD); - attachedButton->addAction( - Supla::SEND_AT_SHORT_PRESS_x1, this, Supla::ON_CLICK_1); - attachedButton->addAction( - Supla::SEND_AT_SHORT_PRESS_x2, this, Supla::ON_CLICK_2); - attachedButton->addAction( - Supla::SEND_AT_SHORT_PRESS_x3, this, Supla::ON_CLICK_3); - attachedButton->addAction( - Supla::SEND_AT_SHORT_PRESS_x4, this, Supla::ON_CLICK_4); - attachedButton->addAction( - Supla::SEND_AT_SHORT_PRESS_x5, this, Supla::ON_CLICK_5); - } - - channel.setDisablesLocalOperation(disablesLocalOperation); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "action_trigger.h" + +Supla::Control::ActionTrigger::ActionTrigger() { + channel.setType(SUPLA_CHANNELTYPE_ACTIONTRIGGER); + channel.setDefault(SUPLA_CHANNELFNC_ACTIONTRIGGER); +} + +Supla::Control::ActionTrigger::~ActionTrigger() {} + +void Supla::Control::ActionTrigger::attach(Supla::Control::Button *button) { + attachedButton = button; +} + +void Supla::Control::ActionTrigger::attach(Supla::Control::Button &button) { + attach(&button); +} + +void Supla::Control::ActionTrigger::handleAction(int event, int action) { + (void)(event); + uint32_t actionCap = getActionTriggerCap(action); + + if (actionCap & activeActionsFromServer) { + channel.pushAction(actionCap); + } +} + +Supla::Channel *Supla::Control::ActionTrigger::getChannel() { + return &channel; +} + +void Supla::Control::ActionTrigger::activateAction(int action) { + channel.activateAction(getActionTriggerCap(action)); +} + +int Supla::Control::ActionTrigger::getActionTriggerCap(int action) { + switch (action) { + case SEND_AT_TURN_ON: { + return SUPLA_ACTION_CAP_TURN_ON; + } + case SEND_AT_TURN_OFF: { + return SUPLA_ACTION_CAP_TURN_OFF; + } + case SEND_AT_TOGGLE_x1: { + return SUPLA_ACTION_CAP_TOGGLE_x1; + } + case SEND_AT_TOGGLE_x2: { + return SUPLA_ACTION_CAP_TOGGLE_x2; + } + case SEND_AT_TOGGLE_x3: { + return SUPLA_ACTION_CAP_TOGGLE_x3; + } + case SEND_AT_TOGGLE_x4: { + return SUPLA_ACTION_CAP_TOGGLE_x4; + } + case SEND_AT_TOGGLE_x5: { + return SUPLA_ACTION_CAP_TOGGLE_x5; + } + case SEND_AT_HOLD: { + return SUPLA_ACTION_CAP_HOLD; + } + case SEND_AT_SHORT_PRESS_x1: { + return SUPLA_ACTION_CAP_SHORT_PRESS_x1; + } + case SEND_AT_SHORT_PRESS_x2: { + return SUPLA_ACTION_CAP_SHORT_PRESS_x2; + } + case SEND_AT_SHORT_PRESS_x3: { + return SUPLA_ACTION_CAP_SHORT_PRESS_x3; + } + case SEND_AT_SHORT_PRESS_x4: { + return SUPLA_ACTION_CAP_SHORT_PRESS_x4; + } + case SEND_AT_SHORT_PRESS_x5: { + return SUPLA_ACTION_CAP_SHORT_PRESS_x5; + } + } + return 0; +} + +int Supla::Control::ActionTrigger::actionTriggerCapToButtonEvent( + uint32_t actionCap) { + switch (actionCap) { + case SUPLA_ACTION_CAP_TURN_ON: { + return Supla::ON_PRESS; + } + case SUPLA_ACTION_CAP_TURN_OFF: { + return Supla::ON_RELEASE; + } + case SUPLA_ACTION_CAP_HOLD: { + return Supla::ON_HOLD; + } + case SUPLA_ACTION_CAP_SHORT_PRESS_x1: + case SUPLA_ACTION_CAP_TOGGLE_x1: { + return Supla::ON_CLICK_1; + } + case SUPLA_ACTION_CAP_SHORT_PRESS_x2: + case SUPLA_ACTION_CAP_TOGGLE_x2: { + return Supla::ON_CLICK_2; + } + case SUPLA_ACTION_CAP_SHORT_PRESS_x3: + case SUPLA_ACTION_CAP_TOGGLE_x3: { + return Supla::ON_CLICK_3; + } + case SUPLA_ACTION_CAP_SHORT_PRESS_x4: + case SUPLA_ACTION_CAP_TOGGLE_x4: { + return Supla::ON_CLICK_4; + } + case SUPLA_ACTION_CAP_SHORT_PRESS_x5: + case SUPLA_ACTION_CAP_TOGGLE_x5: { + return Supla::ON_CLICK_5; + } + } + return 0; +} + + +void Supla::Control::ActionTrigger::onRegistered() { + // cleanup actions to be send + while (channel.popAction()); + + channel.requestChannelConfig(); + +} + +void Supla::Control::ActionTrigger::handleChannelConfig( + TSD_ChannelConfig *result) { + if (result->ConfigType == 0 && + result->ConfigSize == sizeof(TSD_ChannelConfig_ActionTrigger)) { + TSD_ChannelConfig_ActionTrigger *config = + reinterpret_cast(result->Config); + activeActionsFromServer = config->ActiveActions; + Serial.print(F("AT[")); + Serial.print(channel.getChannelNumber()); + Serial.print(F("] received config with active actions: ")); + Serial.println(activeActionsFromServer); + uint32_t actionsToDisable = activeActionsFromServer & disablesLocalOperation; + if (attachedButton) { + for (int i = 0; i < 32; i++) { + uint32_t actionCap = (1 << i); + if (actionsToDisable & actionCap) { + int eventToDisable = actionTriggerCapToButtonEvent(actionCap); + attachedButton->disableOtherClients(this, eventToDisable); + } else if (disablesLocalOperation & actionCap) { + int eventToEnable = actionTriggerCapToButtonEvent(actionCap); + attachedButton->enableOtherClients(this, eventToEnable); + } + } + } + } else { + Serial.println(F("Invalid format of channel config received for AT")); + } +} + +void Supla::Control::ActionTrigger::setRelatedChannel(Element *element) { + if (element && element->getChannel()) { + setRelatedChannel(element->getChannel()); + } +} + +void Supla::Control::ActionTrigger::setRelatedChannel(Element &element) { + setRelatedChannel(&element); +} + +void Supla::Control::ActionTrigger::setRelatedChannel(Channel *relatedChannel) { + if (relatedChannel) { + channel.setRelatedChannel(relatedChannel->getChannelNumber()); + } +} + +void Supla::Control::ActionTrigger::setRelatedChannel(Channel &relatedChannel) { + setRelatedChannel(&relatedChannel); +} + +void Supla::Control::ActionTrigger::onInit() { + if (attachedButton && attachedButton->isBistable()) { + if (attachedButton->isEventAlreadyUsed(Supla::ON_PRESS)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TURN_ON; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_RELEASE)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TURN_OFF; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_1)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x1; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_2)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x2; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_3)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x3; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_4)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x4; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_5)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_TOGGLE_x5; + } + + attachedButton->addAction(Supla::SEND_AT_TURN_ON, this, Supla::ON_PRESS); + attachedButton->addAction(Supla::SEND_AT_TURN_OFF, this, Supla::ON_RELEASE); + attachedButton->addAction( + Supla::SEND_AT_TOGGLE_x1, this, Supla::ON_CLICK_1); + attachedButton->addAction( + Supla::SEND_AT_TOGGLE_x2, this, Supla::ON_CLICK_2); + attachedButton->addAction( + Supla::SEND_AT_TOGGLE_x3, this, Supla::ON_CLICK_3); + attachedButton->addAction( + Supla::SEND_AT_TOGGLE_x4, this, Supla::ON_CLICK_4); + attachedButton->addAction( + Supla::SEND_AT_TOGGLE_x5, this, Supla::ON_CLICK_5); + } + if (attachedButton && !attachedButton->isBistable()) { + if (attachedButton->isEventAlreadyUsed(Supla::ON_HOLD)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_HOLD; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_1)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x1; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_2)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x2; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_3)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x3; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_4)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x4; + } + if (attachedButton->isEventAlreadyUsed(Supla::ON_CLICK_5)) { + disablesLocalOperation |= SUPLA_ACTION_CAP_SHORT_PRESS_x5; + } + + attachedButton->addAction(Supla::SEND_AT_HOLD, this, Supla::ON_HOLD); + attachedButton->addAction( + Supla::SEND_AT_SHORT_PRESS_x1, this, Supla::ON_CLICK_1); + attachedButton->addAction( + Supla::SEND_AT_SHORT_PRESS_x2, this, Supla::ON_CLICK_2); + attachedButton->addAction( + Supla::SEND_AT_SHORT_PRESS_x3, this, Supla::ON_CLICK_3); + attachedButton->addAction( + Supla::SEND_AT_SHORT_PRESS_x4, this, Supla::ON_CLICK_4); + attachedButton->addAction( + Supla::SEND_AT_SHORT_PRESS_x5, this, Supla::ON_CLICK_5); + } + + channel.setDisablesLocalOperation(disablesLocalOperation); +} diff --git a/lib/SuplaDevice/src/supla/control/action_trigger.h b/lib/SuplaDevice/src/supla/control/action_trigger.h index ae997599..ae21221e 100644 --- a/lib/SuplaDevice/src/supla/control/action_trigger.h +++ b/lib/SuplaDevice/src/supla/control/action_trigger.h @@ -1,70 +1,70 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _action_trigger_h -#define _action_trigger_h - -#include -#include "button.h" -#include "../element.h" -#include "../action_handler.h" -#include "../at_channel.h" -#include "../actions.h" - -namespace Supla { -namespace Control { - -class ActionTrigger : public Element, public ActionHandler { - public: - ActionTrigger(); - virtual ~ActionTrigger(); - - // Use below methods to attach button instance to ActionTrigger. - // It will automatically register to all supported button actions - // during onInit() call on action trigger instance. - void attach(Supla::Control::Button *); - void attach(Supla::Control::Button &); - - // Makes AT channel related to other channel, so Supla Cloud will not - // list AT as a separate channel, but it will be extending i.e. Relay - // channel. - void setRelatedChannel(Element *); - void setRelatedChannel(Channel *); - void setRelatedChannel(Element &); - void setRelatedChannel(Channel &); - - void handleAction(int event, int action) override; - void activateAction(int action) override; - Supla::Channel *getChannel() override; - void onInit() override; - void onRegistered() override; - void handleChannelConfig(TSD_ChannelConfig *result) override; - - static int actionTriggerCapToButtonEvent(uint32_t actionCap); - static int getActionTriggerCap(int action); - - protected: - Supla::AtChannel channel; - Supla::Control::Button *attachedButton = nullptr; - uint32_t activeActionsFromServer = 0; - uint32_t disablesLocalOperation = 0; - -}; - -} -} - -#endif /*_action_trigger_h*/ +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _action_trigger_h +#define _action_trigger_h + +#include +#include "button.h" +#include "../element.h" +#include "../action_handler.h" +#include "../at_channel.h" +#include "../actions.h" + +namespace Supla { +namespace Control { + +class ActionTrigger : public Element, public ActionHandler { + public: + ActionTrigger(); + virtual ~ActionTrigger(); + + // Use below methods to attach button instance to ActionTrigger. + // It will automatically register to all supported button actions + // during onInit() call on action trigger instance. + void attach(Supla::Control::Button *); + void attach(Supla::Control::Button &); + + // Makes AT channel related to other channel, so Supla Cloud will not + // list AT as a separate channel, but it will be extending i.e. Relay + // channel. + void setRelatedChannel(Element *); + void setRelatedChannel(Channel *); + void setRelatedChannel(Element &); + void setRelatedChannel(Channel &); + + void handleAction(int event, int action) override; + void activateAction(int action) override; + Supla::Channel *getChannel() override; + void onInit() override; + void onRegistered() override; + void handleChannelConfig(TSD_ChannelConfig *result) override; + + static int actionTriggerCapToButtonEvent(uint32_t actionCap); + static int getActionTriggerCap(int action); + + protected: + Supla::AtChannel channel; + Supla::Control::Button *attachedButton = nullptr; + uint32_t activeActionsFromServer = 0; + uint32_t disablesLocalOperation = 0; + +}; + +} +} + +#endif /*_action_trigger_h*/ diff --git a/lib/SuplaDevice/src/supla/control/button.cpp b/lib/SuplaDevice/src/supla/control/button.cpp index c069652e..fb512b55 100644 --- a/lib/SuplaDevice/src/supla/control/button.cpp +++ b/lib/SuplaDevice/src/supla/control/button.cpp @@ -1,168 +1,168 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "button.h" - - -Supla::Control::Button::Button(int pin, bool pullUp, bool invertLogic) - : SimpleButton(pin, pullUp, invertLogic), - holdTimeMs(0), - repeatOnHoldMs(0), - multiclickTimeMs(0), - lastStateChangeMs(0), - clickCounter(0), - holdSend(0), - bistable(false) { -} - -void Supla::Control::Button::onTimer() { - unsigned int timeDelta = millis() - lastStateChangeMs; - bool stateChanged = false; - int stateResult = state.update(); - if (stateResult == TO_PRESSED) { - stateChanged = true; - runAction(ON_PRESS); - runAction(ON_CHANGE); - } else if (stateResult == TO_RELEASED) { - stateChanged = true; - runAction(ON_RELEASE); - runAction(ON_CHANGE); - } - - if (stateChanged) { - lastStateChangeMs = millis(); - if (stateResult == TO_PRESSED || bistable) { - clickCounter++; - } - } - - if (!stateChanged) { - if (!bistable && stateResult == PRESSED) { - if (clickCounter <= 1 && holdTimeMs > 0 && timeDelta > (holdTimeMs + holdSend*repeatOnHoldMs) && (repeatOnHoldMs == 0 ? !holdSend : true)) { - runAction(ON_HOLD); - ++holdSend; - } - } else if ((bistable || stateResult == RELEASED)) { - if (multiclickTimeMs == 0) { - holdSend = 0; - clickCounter = 0; - } - if (multiclickTimeMs > 0 && timeDelta > multiclickTimeMs) { - if (holdSend == 0) { - switch (clickCounter) { - case 1: - runAction(ON_CLICK_1); - break; - case 2: - runAction(ON_CLICK_2); - break; - case 3: - runAction(ON_CLICK_3); - break; - case 4: - runAction(ON_CLICK_4); - break; - case 5: - runAction(ON_CLICK_5); - break; - case 6: - runAction(ON_CLICK_6); - break; - case 7: - runAction(ON_CLICK_7); - break; - case 8: - runAction(ON_CLICK_8); - break; - case 9: - runAction(ON_CLICK_9); - break; - case 10: - runAction(ON_CLICK_10); - break; - } - if (clickCounter >= 10) { - runAction(ON_CRAZY_CLICKER); - } - } else { - switch (clickCounter) { - // for LONG_CLICK counter was incremented once by ON_HOLD - case 1: - runAction(ON_LONG_CLICK_0); - break; - case 2: - runAction(ON_LONG_CLICK_1); - break; - case 3: - runAction(ON_LONG_CLICK_2); - break; - case 4: - runAction(ON_LONG_CLICK_3); - break; - case 5: - runAction(ON_LONG_CLICK_4); - break; - case 6: - runAction(ON_LONG_CLICK_5); - break; - case 7: - runAction(ON_LONG_CLICK_6); - break; - case 8: - runAction(ON_LONG_CLICK_7); - break; - case 9: - runAction(ON_LONG_CLICK_8); - break; - case 10: - runAction(ON_LONG_CLICK_9); - break; - case 11: - runAction(ON_LONG_CLICK_10); - break; - } - - - } - holdSend = 0; - clickCounter = 0; - } - } - } -} - -void Supla::Control::Button::setHoldTime(unsigned int timeMs) { - holdTimeMs = timeMs; - if (bistable) { - holdTimeMs = 0; - } -} - -void Supla::Control::Button::setMulticlickTime(unsigned int timeMs, bool bistableButton) { - multiclickTimeMs = timeMs; - bistable = bistableButton; - if (bistable) { - holdTimeMs = 0; - } -} - -void Supla::Control::Button::repeatOnHoldEvery(unsigned int timeMs) { - repeatOnHoldMs = timeMs; -} - -bool Supla::Control::Button::isBistable() const { - return bistable; -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "button.h" + + +Supla::Control::Button::Button(int pin, bool pullUp, bool invertLogic) + : SimpleButton(pin, pullUp, invertLogic), + holdTimeMs(0), + repeatOnHoldMs(0), + multiclickTimeMs(0), + lastStateChangeMs(0), + clickCounter(0), + holdSend(0), + bistable(false) { +} + +void Supla::Control::Button::onTimer() { + unsigned int timeDelta = millis() - lastStateChangeMs; + bool stateChanged = false; + int stateResult = state.update(); + if (stateResult == TO_PRESSED) { + stateChanged = true; + runAction(ON_PRESS); + runAction(ON_CHANGE); + } else if (stateResult == TO_RELEASED) { + stateChanged = true; + runAction(ON_RELEASE); + runAction(ON_CHANGE); + } + + if (stateChanged) { + lastStateChangeMs = millis(); + if (stateResult == TO_PRESSED || bistable) { + clickCounter++; + } + } + + if (!stateChanged) { + if (!bistable && stateResult == PRESSED) { + if (clickCounter <= 1 && holdTimeMs > 0 && timeDelta > (holdTimeMs + holdSend*repeatOnHoldMs) && (repeatOnHoldMs == 0 ? !holdSend : true)) { + runAction(ON_HOLD); + ++holdSend; + } + } else if ((bistable || stateResult == RELEASED)) { + if (multiclickTimeMs == 0) { + holdSend = 0; + clickCounter = 0; + } + if (multiclickTimeMs > 0 && timeDelta > multiclickTimeMs) { + if (holdSend == 0) { + switch (clickCounter) { + case 1: + runAction(ON_CLICK_1); + break; + case 2: + runAction(ON_CLICK_2); + break; + case 3: + runAction(ON_CLICK_3); + break; + case 4: + runAction(ON_CLICK_4); + break; + case 5: + runAction(ON_CLICK_5); + break; + case 6: + runAction(ON_CLICK_6); + break; + case 7: + runAction(ON_CLICK_7); + break; + case 8: + runAction(ON_CLICK_8); + break; + case 9: + runAction(ON_CLICK_9); + break; + case 10: + runAction(ON_CLICK_10); + break; + } + if (clickCounter >= 10) { + runAction(ON_CRAZY_CLICKER); + } + } else { + switch (clickCounter) { + // for LONG_CLICK counter was incremented once by ON_HOLD + case 1: + runAction(ON_LONG_CLICK_0); + break; + case 2: + runAction(ON_LONG_CLICK_1); + break; + case 3: + runAction(ON_LONG_CLICK_2); + break; + case 4: + runAction(ON_LONG_CLICK_3); + break; + case 5: + runAction(ON_LONG_CLICK_4); + break; + case 6: + runAction(ON_LONG_CLICK_5); + break; + case 7: + runAction(ON_LONG_CLICK_6); + break; + case 8: + runAction(ON_LONG_CLICK_7); + break; + case 9: + runAction(ON_LONG_CLICK_8); + break; + case 10: + runAction(ON_LONG_CLICK_9); + break; + case 11: + runAction(ON_LONG_CLICK_10); + break; + } + + + } + holdSend = 0; + clickCounter = 0; + } + } + } +} + +void Supla::Control::Button::setHoldTime(unsigned int timeMs) { + holdTimeMs = timeMs; + if (bistable) { + holdTimeMs = 0; + } +} + +void Supla::Control::Button::setMulticlickTime(unsigned int timeMs, bool bistableButton) { + multiclickTimeMs = timeMs; + bistable = bistableButton; + if (bistable) { + holdTimeMs = 0; + } +} + +void Supla::Control::Button::repeatOnHoldEvery(unsigned int timeMs) { + repeatOnHoldMs = timeMs; +} + +bool Supla::Control::Button::isBistable() const { + return bistable; +} diff --git a/lib/SuplaDevice/src/supla/control/button.h b/lib/SuplaDevice/src/supla/control/button.h index e5049046..6bc67e9e 100644 --- a/lib/SuplaDevice/src/supla/control/button.h +++ b/lib/SuplaDevice/src/supla/control/button.h @@ -1,49 +1,49 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _button_h -#define _button_h - -#include -#include "simple_button.h" - -namespace Supla { -namespace Control { - -class Button : public SimpleButton { - public: - Button(int pin, bool pullUp = false, bool invertLogic = false); - - void onTimer(); - void setHoldTime(unsigned int timeMs); - void repeatOnHoldEvery(unsigned int timeMs); - void setMulticlickTime(unsigned int timeMs, bool bistableButton = false); - bool isBistable() const; - - protected: - unsigned int holdTimeMs; - unsigned int repeatOnHoldMs; - unsigned int multiclickTimeMs; - unsigned long lastStateChangeMs; - uint8_t clickCounter; - unsigned int holdSend; - bool bistable; -}; - -}; // namespace Control -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _button_h +#define _button_h + +#include +#include "simple_button.h" + +namespace Supla { +namespace Control { + +class Button : public SimpleButton { + public: + Button(int pin, bool pullUp = false, bool invertLogic = false); + + void onTimer(); + void setHoldTime(unsigned int timeMs); + void repeatOnHoldEvery(unsigned int timeMs); + void setMulticlickTime(unsigned int timeMs, bool bistableButton = false); + bool isBistable() const; + + protected: + unsigned int holdTimeMs; + unsigned int repeatOnHoldMs; + unsigned int multiclickTimeMs; + unsigned long lastStateChangeMs; + uint8_t clickCounter; + unsigned int holdSend; + bool bistable; +}; + +}; // namespace Control +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/control/roller_shutter.cpp b/lib/SuplaDevice/src/supla/control/roller_shutter.cpp index d5db2f05..5e76967f 100644 --- a/lib/SuplaDevice/src/supla/control/roller_shutter.cpp +++ b/lib/SuplaDevice/src/supla/control/roller_shutter.cpp @@ -1,518 +1,518 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include "roller_shutter.h" - -namespace Supla { -namespace Control { - -#pragma pack(push, 1) -struct RollerShutterStateData { - uint32_t closingTimeMs; - uint32_t openingTimeMs; - int8_t currentPosition; // 0 - closed; 100 - opened -}; -#pragma pack(pop) - -RollerShutter::RollerShutter(int pinUp, int pinDown, bool highIsOn) - : closingTimeMs(0), - openingTimeMs(0), - calibrate(true), - comfortDownValue(20), - comfortUpValue(80), - newTargetPositionAvailable(false), - highIsOn(highIsOn), - currentDirection(STOP_DIR), - lastDirection(STOP_DIR), - currentPosition(UNKNOWN_POSITION), - targetPosition(STOP_POSITION), - pinUp(pinUp), - pinDown(pinDown), - lastMovementStartTime(0), - doNothingTime(0), - calibrationTime(0), - operationTimeout(0) { - lastPositionBeforeMovement = currentPosition; - channel.setType(SUPLA_CHANNELTYPE_RELAY); - channel.setDefault(SUPLA_CHANNELFNC_CONTROLLINGTHEROLLERSHUTTER); - channel.setFuncList(SUPLA_BIT_FUNC_CONTROLLINGTHEROLLERSHUTTER); -} - -void RollerShutter::onInit() { - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinUp, highIsOn ? LOW : HIGH); - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinDown, highIsOn ? LOW : HIGH); - Supla::Io::pinMode(channel.getChannelNumber(), pinUp, OUTPUT); - Supla::Io::pinMode(channel.getChannelNumber(), pinDown, OUTPUT); -} - -/* - * Protocol: - * value[0]: - * 0 - stop - * 1 - down - * 2 - up - * 10 - 110 - 0% - 100% - * - * time is send in 0.1 s. i.e. 105 -> 10.5 s - * time * 100 = gives time in ms - * - */ - -int RollerShutter::handleNewValueFromServer( - TSD_SuplaChannelNewValue *newValue) { - uint32_t newClosingTime = (newValue->DurationMS & 0xFFFF) * 100; - uint32_t newOpeningTime = ((newValue->DurationMS >> 16) & 0xFFFF) * 100; - - setOpenCloseTime(newClosingTime, newOpeningTime); - - char task = newValue->value[0]; - Serial.print(F("RollerShutter[")); - Serial.print(channel.getChannelNumber()); - Serial.print(F("] new value from server: ")); - if (task == 0) { - Serial.println(F("STOP")); - stop(); - } else if (task == 1) { - Serial.println(F("MOVE_DOWN")); - moveDown(); - } else if (task == 2) { - Serial.println(F("MOVE_UP")); - moveUp(); - } else if (task >= 10 && task <= 110) { - setTargetPosition(task - 10); - Serial.println(static_cast(task - 10)); - } - - return -1; -} - -void RollerShutter::setOpenCloseTime(uint32_t newClosingTimeMs, - uint32_t newOpeningTimeMs) { - if (newClosingTimeMs == 0) { - newClosingTimeMs = closingTimeMs; - } - if (newOpeningTimeMs == 0) { - newOpeningTimeMs = openingTimeMs; - } - - if (newClosingTimeMs != closingTimeMs || newOpeningTimeMs != openingTimeMs) { - closingTimeMs = newClosingTimeMs; - openingTimeMs = newOpeningTimeMs; - calibrate = true; - currentPosition = UNKNOWN_POSITION; - Serial.print(F("RollerShutter[")); - Serial.print(channel.getChannelNumber()); - Serial.print(F("] new time settings received. Opening time: ")); - Serial.print(openingTimeMs); - Serial.print(F(" ms; closing time: ")); - Serial.print(closingTimeMs); - Serial.println(F(" ms. Starting calibration...")); - } -} - -void RollerShutter::handleAction(int event, int action) { - (void)(event); - switch (action) { - case CLOSE_OR_STOP: { - if (inMove()) { - stop(); - } else { - close(); - } - break; - } - - case CLOSE: { - close(); - break; - } - case OPEN_OR_STOP: { - if (inMove()) { - stop(); - } else { - open(); - } - break; - } - - case OPEN: { - open(); - break; - } - - case COMFORT_DOWN_POSITION: { - setTargetPosition(comfortDownValue); - break; - } - - case COMFORT_UP_POSITION: { - setTargetPosition(comfortUpValue); - break; - } - - case STOP: { - stop(); - break; - } - - case STEP_BY_STEP: { - if (inMove()) { - stop(); - } else if (lastDirectionWasOpen()) { - close(); - } else if (lastDirectionWasClose()) { - open(); - } else if (currentPosition < 50) { - close(); - } else { - open(); - } - break; - } - - case MOVE_UP: { - moveUp(); - break; - } - - case MOVE_DOWN: { - moveDown(); - break; - } - - case MOVE_UP_OR_STOP: { - if (inMove()) { - stop(); - } else { - moveUp(); - } - break; - } - case MOVE_DOWN_OR_STOP: { - if (inMove()) { - stop(); - } else { - moveDown(); - } - break; - } - } -} - -void RollerShutter::close() { - setTargetPosition(100); -} - -void RollerShutter::open() { - setTargetPosition(0); -} - -void RollerShutter::moveDown() { - setTargetPosition(MOVE_DOWN_POSITION); -} - -void RollerShutter::moveUp() { - setTargetPosition(MOVE_UP_POSITION); -} - -void RollerShutter::stop() { - setTargetPosition(STOP_POSITION); -} - -void RollerShutter::setTargetPosition(int newPosition) { - targetPosition = newPosition; - newTargetPositionAvailable = true; - - // Negative targetPosition is either unknown or stop command, so we - // ignore it - if (targetPosition == MOVE_UP_POSITION) { - lastDirection = UP_DIR; - } else if (targetPosition == MOVE_DOWN_POSITION) { - lastDirection = DOWN_DIR; - } else if (targetPosition >= 0) { - if (targetPosition < currentPosition) { - lastDirection = UP_DIR; - } else if (targetPosition > currentPosition) { - lastDirection = DOWN_DIR; - } - } -} - -bool RollerShutter::lastDirectionWasOpen() { - return lastDirection == UP_DIR; -} - -bool RollerShutter::lastDirectionWasClose() { - return lastDirection == DOWN_DIR; -} - -bool RollerShutter::inMove() { - return currentDirection != STOP_DIR; -} - -void RollerShutter::stopMovement() { - switchOffRelays(); - currentDirection = STOP_DIR; - doNothingTime = millis(); - // Schedule save in 5 s after stop movement of roller shutter - Supla::Storage::ScheduleSave(5000); -} - -void RollerShutter::relayDownOn() { - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinDown, highIsOn ? HIGH : LOW); -} - -void RollerShutter::relayUpOn() { - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinUp, highIsOn ? HIGH : LOW); -} - -void RollerShutter::relayDownOff() { - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinDown, highIsOn ? LOW : HIGH); -} - -void RollerShutter::relayUpOff() { - Supla::Io::digitalWrite( - channel.getChannelNumber(), pinUp, highIsOn ? LOW : HIGH); -} - -void RollerShutter::startClosing() { - currentDirection = DOWN_DIR; - relayUpOff(); // just to make sure - relayDownOn(); -} - -void RollerShutter::startOpening() { - currentDirection = UP_DIR; - relayDownOff(); // just to make sure - relayUpOn(); -} - -void RollerShutter::switchOffRelays() { - relayUpOff(); - relayDownOff(); -} - -void RollerShutter::onTimer() { - if (millis() - doNothingTime < - 300) { // doNothingTime time is used when we change - // direction of roller - to stop for a moment - // before enabling opposite direction - return; - } - - if (operationTimeout != 0 && - millis() - lastMovementStartTime > operationTimeout) { - setTargetPosition(STOP_POSITION); - operationTimeout = 0; - } - - if (targetPosition == STOP_POSITION && inMove()) { - stopMovement(); - calibrationTime = 0; - } - - if (calibrate && targetPosition == STOP_POSITION) { - return; - } else if (calibrate) { - // If calibrationTime is not set, then it means we should start calibration - if (calibrationTime == 0) { - // If roller shutter wasn't in move when calibration is requested, we - // select direction based on requested targetPosition - operationTimeout = 0; - if (targetPosition > 50 || targetPosition == MOVE_DOWN_POSITION) { - if (currentDirection == UP_DIR) { - stopMovement(); - } else if (currentDirection == STOP_DIR) { - Serial.println(F("Calibration: closing")); - calibrationTime = closingTimeMs; - lastMovementStartTime = millis(); - if (calibrationTime == 0) { - operationTimeout = 60000; - } - startClosing(); - } - } else { - if (currentDirection == DOWN_DIR) { - stopMovement(); - } else if (currentDirection == STOP_DIR) { - Serial.println(F("Calibration: opening")); - calibrationTime = openingTimeMs; - lastMovementStartTime = millis(); - if (calibrationTime == 0) { - operationTimeout = 60000; - } - startOpening(); - } - } - // - // Time used for calibaration is 10% higher then requested by user - calibrationTime *= 1.1; - if (calibrationTime > 0) { - Serial.print(F("Calibration time: ")); - Serial.println(calibrationTime); - } - } - - if (calibrationTime != 0 && - millis() - lastMovementStartTime > calibrationTime) { - Serial.println(F("Calibration done")); - calibrationTime = 0; - calibrate = false; - if (currentDirection == UP_DIR) { - currentPosition = 0; - } else { - currentPosition = 100; - } - stopMovement(); - } - - } else if (!newTargetPositionAvailable && - currentDirection != - STOP_DIR) { // no new command available and it is moving, - // just handle roller movement/status - if (currentDirection == UP_DIR && currentPosition > 0) { - int movementDistance = lastPositionBeforeMovement; - uint32_t timeRequired = (1.0 * openingTimeMs * movementDistance / 100.0); - float fractionOfMovemendDone = - (1.0 * (millis() - lastMovementStartTime) / timeRequired); - if (fractionOfMovemendDone > 1) { - fractionOfMovemendDone = 1; - } - currentPosition = lastPositionBeforeMovement - - movementDistance * fractionOfMovemendDone; - if (targetPosition >= 0 && currentPosition <= targetPosition) { - stopMovement(); - } - } else if (currentDirection == DOWN_DIR && currentPosition < 100) { - int movementDistance = 100 - lastPositionBeforeMovement; - uint32_t timeRequired = (1.0 * closingTimeMs * movementDistance / 100.0); - float fractionOfMovemendDone = - (1.0 * (millis() - lastMovementStartTime) / timeRequired); - if (fractionOfMovemendDone > 1) { - fractionOfMovemendDone = 1; - } - currentPosition = lastPositionBeforeMovement + - movementDistance * fractionOfMovemendDone; - if (targetPosition >= 0 && currentPosition >= targetPosition) { - stopMovement(); - } - } - - if (currentPosition > 100) { - currentPosition = 100; - } else if (currentPosition < 0) { - currentPosition = 0; - } - - } else if (newTargetPositionAvailable && targetPosition != STOP_POSITION) { - // new target state was set, let's handle it - int newDirection = STOP_DIR; - if (targetPosition == MOVE_UP_POSITION) { - newDirection = UP_DIR; - operationTimeout = 60000; - } else if (targetPosition == MOVE_DOWN_POSITION) { - newDirection = DOWN_DIR; - operationTimeout = 60000; - } else { - operationTimeout = 0; - int newMovementValue = targetPosition - currentPosition; - // 0 - 100 = -100 (move down); 50 - - // 20 = 30 (move up 30%), etc - if (newMovementValue > 0) { - newDirection = DOWN_DIR; // move down - } else if (newMovementValue < 0) { - newDirection = UP_DIR; // move up - } - } - // If new direction is the same as current move, then keep movin` - if (newDirection == currentDirection) { - newTargetPositionAvailable = false; - } else if (currentDirection == STOP_DIR) { // else start moving - newTargetPositionAvailable = false; - lastPositionBeforeMovement = currentPosition; - lastMovementStartTime = millis(); - if (newDirection == DOWN_DIR) { - startClosing(); - } else { - startOpening(); - } - } else { // else stop before changing direction - stopMovement(); - } - } - // if (newCurrentPosition != currentPosition) { - // currentPosition = newCurrentPosition; - TRollerShutterValue value = {}; - value.position = currentPosition; - channel.setNewValue(value); -} - -void RollerShutter::configComfortUpValue(uint8_t position) { - comfortUpValue = position; - if (comfortUpValue > 100) { - comfortUpValue = 100; - } -} - -void RollerShutter::configComfortDownValue(uint8_t position) { - comfortDownValue = position; - if (comfortDownValue > 100) { - comfortDownValue = 100; - } -} - -void RollerShutter::onLoadState() { - RollerShutterStateData data = RollerShutterStateData(); - if (Supla::Storage::ReadState((unsigned char *)&data, sizeof(data))) { - closingTimeMs = data.closingTimeMs; - openingTimeMs = data.openingTimeMs; - currentPosition = data.currentPosition; - if (currentPosition >= 0) { - calibrate = false; - } - Serial.print(F("RollerShutter[")); - Serial.print(channel.getChannelNumber()); - Serial.print(F("] settings restored from storage. Opening time: ")); - Serial.print(openingTimeMs); - Serial.print(F(" ms; closing time: ")); - Serial.print(closingTimeMs); - Serial.print(F(" ms. Position: ")); - Serial.println(currentPosition); - } -} - -void RollerShutter::onSaveState() { - RollerShutterStateData data; - data.closingTimeMs = closingTimeMs; - data.openingTimeMs = openingTimeMs; - data.currentPosition = currentPosition; - - Supla::Storage::WriteState((unsigned char *)&data, sizeof(data)); -} - -int RollerShutter::getCurrentPosition() { - return currentPosition; -} - -}; // namespace Control -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "roller_shutter.h" + +namespace Supla { +namespace Control { + +#pragma pack(push, 1) +struct RollerShutterStateData { + uint32_t closingTimeMs; + uint32_t openingTimeMs; + int8_t currentPosition; // 0 - closed; 100 - opened +}; +#pragma pack(pop) + +RollerShutter::RollerShutter(int pinUp, int pinDown, bool highIsOn) + : closingTimeMs(0), + openingTimeMs(0), + calibrate(true), + comfortDownValue(20), + comfortUpValue(80), + newTargetPositionAvailable(false), + highIsOn(highIsOn), + currentDirection(STOP_DIR), + lastDirection(STOP_DIR), + currentPosition(UNKNOWN_POSITION), + targetPosition(STOP_POSITION), + pinUp(pinUp), + pinDown(pinDown), + lastMovementStartTime(0), + doNothingTime(0), + calibrationTime(0), + operationTimeout(0) { + lastPositionBeforeMovement = currentPosition; + channel.setType(SUPLA_CHANNELTYPE_RELAY); + channel.setDefault(SUPLA_CHANNELFNC_CONTROLLINGTHEROLLERSHUTTER); + channel.setFuncList(SUPLA_BIT_FUNC_CONTROLLINGTHEROLLERSHUTTER); +} + +void RollerShutter::onInit() { + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinUp, highIsOn ? LOW : HIGH); + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinDown, highIsOn ? LOW : HIGH); + Supla::Io::pinMode(channel.getChannelNumber(), pinUp, OUTPUT); + Supla::Io::pinMode(channel.getChannelNumber(), pinDown, OUTPUT); +} + +/* + * Protocol: + * value[0]: + * 0 - stop + * 1 - down + * 2 - up + * 10 - 110 - 0% - 100% + * + * time is send in 0.1 s. i.e. 105 -> 10.5 s + * time * 100 = gives time in ms + * + */ + +int RollerShutter::handleNewValueFromServer( + TSD_SuplaChannelNewValue *newValue) { + uint32_t newClosingTime = (newValue->DurationMS & 0xFFFF) * 100; + uint32_t newOpeningTime = ((newValue->DurationMS >> 16) & 0xFFFF) * 100; + + setOpenCloseTime(newClosingTime, newOpeningTime); + + char task = newValue->value[0]; + Serial.print(F("RollerShutter[")); + Serial.print(channel.getChannelNumber()); + Serial.print(F("] new value from server: ")); + if (task == 0) { + Serial.println(F("STOP")); + stop(); + } else if (task == 1) { + Serial.println(F("MOVE_DOWN")); + moveDown(); + } else if (task == 2) { + Serial.println(F("MOVE_UP")); + moveUp(); + } else if (task >= 10 && task <= 110) { + setTargetPosition(task - 10); + Serial.println(static_cast(task - 10)); + } + + return -1; +} + +void RollerShutter::setOpenCloseTime(uint32_t newClosingTimeMs, + uint32_t newOpeningTimeMs) { + if (newClosingTimeMs == 0) { + newClosingTimeMs = closingTimeMs; + } + if (newOpeningTimeMs == 0) { + newOpeningTimeMs = openingTimeMs; + } + + if (newClosingTimeMs != closingTimeMs || newOpeningTimeMs != openingTimeMs) { + closingTimeMs = newClosingTimeMs; + openingTimeMs = newOpeningTimeMs; + calibrate = true; + currentPosition = UNKNOWN_POSITION; + Serial.print(F("RollerShutter[")); + Serial.print(channel.getChannelNumber()); + Serial.print(F("] new time settings received. Opening time: ")); + Serial.print(openingTimeMs); + Serial.print(F(" ms; closing time: ")); + Serial.print(closingTimeMs); + Serial.println(F(" ms. Starting calibration...")); + } +} + +void RollerShutter::handleAction(int event, int action) { + (void)(event); + switch (action) { + case CLOSE_OR_STOP: { + if (inMove()) { + stop(); + } else { + close(); + } + break; + } + + case CLOSE: { + close(); + break; + } + case OPEN_OR_STOP: { + if (inMove()) { + stop(); + } else { + open(); + } + break; + } + + case OPEN: { + open(); + break; + } + + case COMFORT_DOWN_POSITION: { + setTargetPosition(comfortDownValue); + break; + } + + case COMFORT_UP_POSITION: { + setTargetPosition(comfortUpValue); + break; + } + + case STOP: { + stop(); + break; + } + + case STEP_BY_STEP: { + if (inMove()) { + stop(); + } else if (lastDirectionWasOpen()) { + close(); + } else if (lastDirectionWasClose()) { + open(); + } else if (currentPosition < 50) { + close(); + } else { + open(); + } + break; + } + + case MOVE_UP: { + moveUp(); + break; + } + + case MOVE_DOWN: { + moveDown(); + break; + } + + case MOVE_UP_OR_STOP: { + if (inMove()) { + stop(); + } else { + moveUp(); + } + break; + } + case MOVE_DOWN_OR_STOP: { + if (inMove()) { + stop(); + } else { + moveDown(); + } + break; + } + } +} + +void RollerShutter::close() { + setTargetPosition(100); +} + +void RollerShutter::open() { + setTargetPosition(0); +} + +void RollerShutter::moveDown() { + setTargetPosition(MOVE_DOWN_POSITION); +} + +void RollerShutter::moveUp() { + setTargetPosition(MOVE_UP_POSITION); +} + +void RollerShutter::stop() { + setTargetPosition(STOP_POSITION); +} + +void RollerShutter::setTargetPosition(int newPosition) { + targetPosition = newPosition; + newTargetPositionAvailable = true; + + // Negative targetPosition is either unknown or stop command, so we + // ignore it + if (targetPosition == MOVE_UP_POSITION) { + lastDirection = UP_DIR; + } else if (targetPosition == MOVE_DOWN_POSITION) { + lastDirection = DOWN_DIR; + } else if (targetPosition >= 0) { + if (targetPosition < currentPosition) { + lastDirection = UP_DIR; + } else if (targetPosition > currentPosition) { + lastDirection = DOWN_DIR; + } + } +} + +bool RollerShutter::lastDirectionWasOpen() { + return lastDirection == UP_DIR; +} + +bool RollerShutter::lastDirectionWasClose() { + return lastDirection == DOWN_DIR; +} + +bool RollerShutter::inMove() { + return currentDirection != STOP_DIR; +} + +void RollerShutter::stopMovement() { + switchOffRelays(); + currentDirection = STOP_DIR; + doNothingTime = millis(); + // Schedule save in 5 s after stop movement of roller shutter + Supla::Storage::ScheduleSave(5000); +} + +void RollerShutter::relayDownOn() { + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinDown, highIsOn ? HIGH : LOW); +} + +void RollerShutter::relayUpOn() { + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinUp, highIsOn ? HIGH : LOW); +} + +void RollerShutter::relayDownOff() { + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinDown, highIsOn ? LOW : HIGH); +} + +void RollerShutter::relayUpOff() { + Supla::Io::digitalWrite( + channel.getChannelNumber(), pinUp, highIsOn ? LOW : HIGH); +} + +void RollerShutter::startClosing() { + currentDirection = DOWN_DIR; + relayUpOff(); // just to make sure + relayDownOn(); +} + +void RollerShutter::startOpening() { + currentDirection = UP_DIR; + relayDownOff(); // just to make sure + relayUpOn(); +} + +void RollerShutter::switchOffRelays() { + relayUpOff(); + relayDownOff(); +} + +void RollerShutter::onTimer() { + if (millis() - doNothingTime < + 300) { // doNothingTime time is used when we change + // direction of roller - to stop for a moment + // before enabling opposite direction + return; + } + + if (operationTimeout != 0 && + millis() - lastMovementStartTime > operationTimeout) { + setTargetPosition(STOP_POSITION); + operationTimeout = 0; + } + + if (targetPosition == STOP_POSITION && inMove()) { + stopMovement(); + calibrationTime = 0; + } + + if (calibrate && targetPosition == STOP_POSITION) { + return; + } else if (calibrate) { + // If calibrationTime is not set, then it means we should start calibration + if (calibrationTime == 0) { + // If roller shutter wasn't in move when calibration is requested, we + // select direction based on requested targetPosition + operationTimeout = 0; + if (targetPosition > 50 || targetPosition == MOVE_DOWN_POSITION) { + if (currentDirection == UP_DIR) { + stopMovement(); + } else if (currentDirection == STOP_DIR) { + Serial.println(F("Calibration: closing")); + calibrationTime = closingTimeMs; + lastMovementStartTime = millis(); + if (calibrationTime == 0) { + operationTimeout = 60000; + } + startClosing(); + } + } else { + if (currentDirection == DOWN_DIR) { + stopMovement(); + } else if (currentDirection == STOP_DIR) { + Serial.println(F("Calibration: opening")); + calibrationTime = openingTimeMs; + lastMovementStartTime = millis(); + if (calibrationTime == 0) { + operationTimeout = 60000; + } + startOpening(); + } + } + // + // Time used for calibaration is 10% higher then requested by user + calibrationTime *= 1.1; + if (calibrationTime > 0) { + Serial.print(F("Calibration time: ")); + Serial.println(calibrationTime); + } + } + + if (calibrationTime != 0 && + millis() - lastMovementStartTime > calibrationTime) { + Serial.println(F("Calibration done")); + calibrationTime = 0; + calibrate = false; + if (currentDirection == UP_DIR) { + currentPosition = 0; + } else { + currentPosition = 100; + } + stopMovement(); + } + + } else if (!newTargetPositionAvailable && + currentDirection != + STOP_DIR) { // no new command available and it is moving, + // just handle roller movement/status + if (currentDirection == UP_DIR && currentPosition > 0) { + int movementDistance = lastPositionBeforeMovement; + uint32_t timeRequired = (1.0 * openingTimeMs * movementDistance / 100.0); + float fractionOfMovemendDone = + (1.0 * (millis() - lastMovementStartTime) / timeRequired); + if (fractionOfMovemendDone > 1) { + fractionOfMovemendDone = 1; + } + currentPosition = lastPositionBeforeMovement - + movementDistance * fractionOfMovemendDone; + if (targetPosition >= 0 && currentPosition <= targetPosition) { + stopMovement(); + } + } else if (currentDirection == DOWN_DIR && currentPosition < 100) { + int movementDistance = 100 - lastPositionBeforeMovement; + uint32_t timeRequired = (1.0 * closingTimeMs * movementDistance / 100.0); + float fractionOfMovemendDone = + (1.0 * (millis() - lastMovementStartTime) / timeRequired); + if (fractionOfMovemendDone > 1) { + fractionOfMovemendDone = 1; + } + currentPosition = lastPositionBeforeMovement + + movementDistance * fractionOfMovemendDone; + if (targetPosition >= 0 && currentPosition >= targetPosition) { + stopMovement(); + } + } + + if (currentPosition > 100) { + currentPosition = 100; + } else if (currentPosition < 0) { + currentPosition = 0; + } + + } else if (newTargetPositionAvailable && targetPosition != STOP_POSITION) { + // new target state was set, let's handle it + int newDirection = STOP_DIR; + if (targetPosition == MOVE_UP_POSITION) { + newDirection = UP_DIR; + operationTimeout = 60000; + } else if (targetPosition == MOVE_DOWN_POSITION) { + newDirection = DOWN_DIR; + operationTimeout = 60000; + } else { + operationTimeout = 0; + int newMovementValue = targetPosition - currentPosition; + // 0 - 100 = -100 (move down); 50 - + // 20 = 30 (move up 30%), etc + if (newMovementValue > 0) { + newDirection = DOWN_DIR; // move down + } else if (newMovementValue < 0) { + newDirection = UP_DIR; // move up + } + } + // If new direction is the same as current move, then keep movin` + if (newDirection == currentDirection) { + newTargetPositionAvailable = false; + } else if (currentDirection == STOP_DIR) { // else start moving + newTargetPositionAvailable = false; + lastPositionBeforeMovement = currentPosition; + lastMovementStartTime = millis(); + if (newDirection == DOWN_DIR) { + startClosing(); + } else { + startOpening(); + } + } else { // else stop before changing direction + stopMovement(); + } + } + // if (newCurrentPosition != currentPosition) { + // currentPosition = newCurrentPosition; + TRollerShutterValue value = {}; + value.position = currentPosition; + channel.setNewValue(value); +} + +void RollerShutter::configComfortUpValue(uint8_t position) { + comfortUpValue = position; + if (comfortUpValue > 100) { + comfortUpValue = 100; + } +} + +void RollerShutter::configComfortDownValue(uint8_t position) { + comfortDownValue = position; + if (comfortDownValue > 100) { + comfortDownValue = 100; + } +} + +void RollerShutter::onLoadState() { + RollerShutterStateData data = RollerShutterStateData(); + if (Supla::Storage::ReadState((unsigned char *)&data, sizeof(data))) { + closingTimeMs = data.closingTimeMs; + openingTimeMs = data.openingTimeMs; + currentPosition = data.currentPosition; + if (currentPosition >= 0) { + calibrate = false; + } + Serial.print(F("RollerShutter[")); + Serial.print(channel.getChannelNumber()); + Serial.print(F("] settings restored from storage. Opening time: ")); + Serial.print(openingTimeMs); + Serial.print(F(" ms; closing time: ")); + Serial.print(closingTimeMs); + Serial.print(F(" ms. Position: ")); + Serial.println(currentPosition); + } +} + +void RollerShutter::onSaveState() { + RollerShutterStateData data; + data.closingTimeMs = closingTimeMs; + data.openingTimeMs = openingTimeMs; + data.currentPosition = currentPosition; + + Supla::Storage::WriteState((unsigned char *)&data, sizeof(data)); +} + +int RollerShutter::getCurrentPosition() { + return currentPosition; +} + +}; // namespace Control +}; // namespace Supla diff --git a/lib/SuplaDevice/src/supla/control/simple_button.cpp b/lib/SuplaDevice/src/supla/control/simple_button.cpp index 533eb5ac..e7322bf8 100644 --- a/lib/SuplaDevice/src/supla/control/simple_button.cpp +++ b/lib/SuplaDevice/src/supla/control/simple_button.cpp @@ -1,108 +1,108 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "button.h" -#include "../io.h" - -Supla::Control::ButtonState::ButtonState(int pin, bool pullUp, bool invertLogic) - : debounceTimeMs(0), - filterTimeMs(0), - debounceDelayMs(50), - swNoiseFilterDelayMs(20), - pin(pin), - newStatusCandidate(LOW), - prevState(LOW), - pullUp(pullUp), - invertLogic(invertLogic) { -} - -int Supla::Control::ButtonState::update() { - unsigned long curMillis = millis(); - if (debounceDelayMs == 0 || curMillis - debounceTimeMs > debounceDelayMs) { - int currentState = Supla::Io::digitalRead(pin); - if (currentState != prevState) { - // If status is changed, then make sure that it will be kept at - // least swNoiseFilterDelayMs ms to avoid noise - if (swNoiseFilterDelayMs != 0 && currentState != newStatusCandidate) { - newStatusCandidate = currentState; - filterTimeMs = curMillis; - } else if (curMillis - filterTimeMs > swNoiseFilterDelayMs) { - // If new status is kept at least swNoiseFilterDelayMs ms, then apply - // change of status - debounceTimeMs = curMillis; - prevState = currentState; - if (currentState == valueOnPress()) { - return TO_PRESSED; - } else { - return TO_RELEASED; - } - } - } else { - // If current status is the same as prevState, then reset - // new status candidate - newStatusCandidate = prevState; - } - } - if (prevState == valueOnPress()) { - return PRESSED; - } else { - return RELEASED; - } -} - -Supla::Control::SimpleButton::SimpleButton(int pin, bool pullUp, bool invertLogic) - : state(pin, pullUp, invertLogic) { -} - -void Supla::Control::SimpleButton::onTimer() { - int stateResult = state.update(); - if (stateResult == TO_PRESSED) { - runAction(ON_PRESS); - runAction(ON_CHANGE); - } else if (stateResult == TO_RELEASED) { - runAction(ON_RELEASE); - runAction(ON_CHANGE); - } -} - -void Supla::Control::SimpleButton::onInit() { - state.init(); -} - -void Supla::Control::ButtonState::init() { - Supla::Io::pinMode(pin, pullUp ? INPUT_PULLUP : INPUT); - prevState = Supla::Io::digitalRead(pin); - newStatusCandidate = prevState; -} - -int Supla::Control::ButtonState::valueOnPress() { - return invertLogic ? LOW : HIGH; -} - -void Supla::Control::SimpleButton::setSwNoiseFilterDelay(unsigned int newDelayMs) { - state.setSwNoiseFilterDelay(newDelayMs); -} -void Supla::Control::ButtonState::setSwNoiseFilterDelay(unsigned int newDelayMs) { - swNoiseFilterDelayMs = newDelayMs; -} - -void Supla::Control::SimpleButton::setDebounceDelay(unsigned int newDelayMs) { - state.setDebounceDelay(newDelayMs); -} - -void Supla::Control::ButtonState::setDebounceDelay(unsigned int newDelayMs) { - debounceDelayMs = newDelayMs; -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "button.h" +#include "../io.h" + +Supla::Control::ButtonState::ButtonState(int pin, bool pullUp, bool invertLogic) + : debounceTimeMs(0), + filterTimeMs(0), + debounceDelayMs(50), + swNoiseFilterDelayMs(20), + pin(pin), + newStatusCandidate(LOW), + prevState(LOW), + pullUp(pullUp), + invertLogic(invertLogic) { +} + +int Supla::Control::ButtonState::update() { + unsigned long curMillis = millis(); + if (debounceDelayMs == 0 || curMillis - debounceTimeMs > debounceDelayMs) { + int currentState = Supla::Io::digitalRead(pin); + if (currentState != prevState) { + // If status is changed, then make sure that it will be kept at + // least swNoiseFilterDelayMs ms to avoid noise + if (swNoiseFilterDelayMs != 0 && currentState != newStatusCandidate) { + newStatusCandidate = currentState; + filterTimeMs = curMillis; + } else if (curMillis - filterTimeMs > swNoiseFilterDelayMs) { + // If new status is kept at least swNoiseFilterDelayMs ms, then apply + // change of status + debounceTimeMs = curMillis; + prevState = currentState; + if (currentState == valueOnPress()) { + return TO_PRESSED; + } else { + return TO_RELEASED; + } + } + } else { + // If current status is the same as prevState, then reset + // new status candidate + newStatusCandidate = prevState; + } + } + if (prevState == valueOnPress()) { + return PRESSED; + } else { + return RELEASED; + } +} + +Supla::Control::SimpleButton::SimpleButton(int pin, bool pullUp, bool invertLogic) + : state(pin, pullUp, invertLogic) { +} + +void Supla::Control::SimpleButton::onTimer() { + int stateResult = state.update(); + if (stateResult == TO_PRESSED) { + runAction(ON_PRESS); + runAction(ON_CHANGE); + } else if (stateResult == TO_RELEASED) { + runAction(ON_RELEASE); + runAction(ON_CHANGE); + } +} + +void Supla::Control::SimpleButton::onInit() { + state.init(); +} + +void Supla::Control::ButtonState::init() { + Supla::Io::pinMode(pin, pullUp ? INPUT_PULLUP : INPUT); + prevState = Supla::Io::digitalRead(pin); + newStatusCandidate = prevState; +} + +int Supla::Control::ButtonState::valueOnPress() { + return invertLogic ? LOW : HIGH; +} + +void Supla::Control::SimpleButton::setSwNoiseFilterDelay(unsigned int newDelayMs) { + state.setSwNoiseFilterDelay(newDelayMs); +} +void Supla::Control::ButtonState::setSwNoiseFilterDelay(unsigned int newDelayMs) { + swNoiseFilterDelayMs = newDelayMs; +} + +void Supla::Control::SimpleButton::setDebounceDelay(unsigned int newDelayMs) { + state.setDebounceDelay(newDelayMs); +} + +void Supla::Control::ButtonState::setDebounceDelay(unsigned int newDelayMs) { + debounceDelayMs = newDelayMs; +} diff --git a/lib/SuplaDevice/src/supla/element.cpp b/lib/SuplaDevice/src/supla/element.cpp index 85b121d8..a8de7ecb 100644 --- a/lib/SuplaDevice/src/supla/element.cpp +++ b/lib/SuplaDevice/src/supla/element.cpp @@ -1,151 +1,151 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include "supla/element.h" - -namespace Supla { -Element *Element::firstPtr = nullptr; - -Element::Element() : nextPtr(nullptr) { - if (firstPtr == nullptr) { - firstPtr = this; - } else { - last()->nextPtr = this; - } -} - -Element::~Element() { - if (begin() == this) { - firstPtr = next(); - return; - } - - auto ptr = begin(); - while (ptr->next() != this) { - ptr = ptr->next(); - } - - ptr->nextPtr = ptr->next()->next(); -} - -Element *Element::begin() { - return firstPtr; -} - -Element *Element::last() { - Element *ptr = firstPtr; - while (ptr && ptr->nextPtr) { - ptr = ptr->nextPtr; - } - return ptr; -} - -Element *Element::getElementByChannelNumber(int channelNumber) { - Element *element = begin(); - while (element != nullptr && element->getChannelNumber() != channelNumber) { - element = element->next(); - } - - return element; -} - -Element *Element::next() { - return nextPtr; -} - -void Element::onInit(){}; - -void Element::onLoadState(){}; - -void Element::onSaveState(){}; - -void Element::onRegistered(){}; - -void Element::iterateAlways(){}; - -bool Element::iterateConnected(void *srpc) { - bool response = true; - unsigned long timestamp = millis(); - Channel *secondaryChannel = getSecondaryChannel(); - if (secondaryChannel && secondaryChannel->isUpdateReady() && - timestamp - secondaryChannel->lastCommunicationTimeMs > 100) { - secondaryChannel->lastCommunicationTimeMs = timestamp; - secondaryChannel->sendUpdate(srpc); - response = false; - } - - Channel *channel = getChannel(); - if (channel && channel->isUpdateReady() && - timestamp - channel->lastCommunicationTimeMs > 100) { - channel->lastCommunicationTimeMs = timestamp; - channel->sendUpdate(srpc); - response = false; - } - return response; -} - -void Element::onTimer(){}; - -void Element::onFastTimer(){}; - -int Element::handleNewValueFromServer(TSD_SuplaChannelNewValue *newValue) { - (void)(newValue); - return -1; -} - -int Element::getChannelNumber() { - int result = -1; - Channel *channel = getChannel(); - if (channel) { - result = channel->getChannelNumber(); - } - return result; -} - -Channel *Element::getChannel() { - return nullptr; -} - -Channel *Element::getSecondaryChannel() { - return nullptr; -} - -void Element::handleGetChannelState(TDSC_ChannelState &channelState) { - (void)(channelState); - return; -} - -int Element::handleCalcfgFromServer(TSD_DeviceCalCfgRequest *request) { - (void)(request); - return SUPLA_CALCFG_RESULT_NOT_SUPPORTED; -} - -Element & Element::disableChannelState() { - if (getChannel()) { - getChannel()->unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); - } - return *this; -} - -void Element::handleChannelConfig(TSD_ChannelConfig *result) { - Serial.print(F("Channel[")); - Serial.print(result->ChannelNumber); - Serial.println(F("]: received channel config reply, but handling is missing")); -} - -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "supla/element.h" + +namespace Supla { +Element *Element::firstPtr = nullptr; + +Element::Element() : nextPtr(nullptr) { + if (firstPtr == nullptr) { + firstPtr = this; + } else { + last()->nextPtr = this; + } +} + +Element::~Element() { + if (begin() == this) { + firstPtr = next(); + return; + } + + auto ptr = begin(); + while (ptr->next() != this) { + ptr = ptr->next(); + } + + ptr->nextPtr = ptr->next()->next(); +} + +Element *Element::begin() { + return firstPtr; +} + +Element *Element::last() { + Element *ptr = firstPtr; + while (ptr && ptr->nextPtr) { + ptr = ptr->nextPtr; + } + return ptr; +} + +Element *Element::getElementByChannelNumber(int channelNumber) { + Element *element = begin(); + while (element != nullptr && element->getChannelNumber() != channelNumber) { + element = element->next(); + } + + return element; +} + +Element *Element::next() { + return nextPtr; +} + +void Element::onInit(){}; + +void Element::onLoadState(){}; + +void Element::onSaveState(){}; + +void Element::onRegistered(){}; + +void Element::iterateAlways(){}; + +bool Element::iterateConnected(void *srpc) { + bool response = true; + unsigned long timestamp = millis(); + Channel *secondaryChannel = getSecondaryChannel(); + if (secondaryChannel && secondaryChannel->isUpdateReady() && + timestamp - secondaryChannel->lastCommunicationTimeMs > 100) { + secondaryChannel->lastCommunicationTimeMs = timestamp; + secondaryChannel->sendUpdate(srpc); + response = false; + } + + Channel *channel = getChannel(); + if (channel && channel->isUpdateReady() && + timestamp - channel->lastCommunicationTimeMs > 100) { + channel->lastCommunicationTimeMs = timestamp; + channel->sendUpdate(srpc); + response = false; + } + return response; +} + +void Element::onTimer(){}; + +void Element::onFastTimer(){}; + +int Element::handleNewValueFromServer(TSD_SuplaChannelNewValue *newValue) { + (void)(newValue); + return -1; +} + +int Element::getChannelNumber() { + int result = -1; + Channel *channel = getChannel(); + if (channel) { + result = channel->getChannelNumber(); + } + return result; +} + +Channel *Element::getChannel() { + return nullptr; +} + +Channel *Element::getSecondaryChannel() { + return nullptr; +} + +void Element::handleGetChannelState(TDSC_ChannelState &channelState) { + (void)(channelState); + return; +} + +int Element::handleCalcfgFromServer(TSD_DeviceCalCfgRequest *request) { + (void)(request); + return SUPLA_CALCFG_RESULT_NOT_SUPPORTED; +} + +Element & Element::disableChannelState() { + if (getChannel()) { + getChannel()->unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); + } + return *this; +} + +void Element::handleChannelConfig(TSD_ChannelConfig *result) { + Serial.print(F("Channel[")); + Serial.print(result->ChannelNumber); + Serial.println(F("]: received channel config reply, but handling is missing")); +} + +}; // namespace Supla diff --git a/lib/SuplaDevice/src/supla/element.h b/lib/SuplaDevice/src/supla/element.h index d083728d..0849feaf 100644 --- a/lib/SuplaDevice/src/supla/element.h +++ b/lib/SuplaDevice/src/supla/element.h @@ -1,96 +1,96 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _element_h -#define _element_h - -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) -#include -#endif -#include "channel.h" - -namespace Supla { - -class Element { - public: - Element(); - virtual ~Element(); - static Element *begin(); - static Element *last(); - static Element *getElementByChannelNumber(int channelNumber); - Element *next(); - - // method called during SuplaDevice initialization. I.e. load initial state, - // initialize pins etc. - virtual void onInit(); - - // method called during Config initialization (i.e. read from EEPROM, FRAM). - // Called only if Storage class is configured - virtual void onLoadState(); - - // method called periodically during SuplaDevice iteration - // Called only if Storage class is configured - virtual void onSaveState(); - - // method called each time when device successfully registers to server - virtual void onRegistered(); - - // method called on each SuplaDevice iteration (before Network layer - // iteration). When Device is connected, both iterateAlways() and - // iterateConnected() are called. - virtual void iterateAlways(); - - // method called on each Supla::Device iteration when Device is connected and - // registered to Supla server - virtual bool iterateConnected(void *srpc); - - // method called on timer interupt - // Include all actions that have to be executed periodically regardless of - // other SuplaDevice activities - virtual void onTimer(); - - // method called on fast timer interupt - // Include all actions that have to be executed periodically regardless of - // other SuplaDevice activities - virtual void onFastTimer(); - - // return value: - // -1 - don't send reply to server - // 0 - success==false - // 1 - success==true - virtual int handleNewValueFromServer(TSD_SuplaChannelNewValue *newValue); - - // Handles "get channel state" request from server - // channelState is prefilled with network and device status informations - virtual void handleGetChannelState(TDSC_ChannelState &channelState); - - virtual int handleCalcfgFromServer(TSD_DeviceCalCfgRequest *request); - virtual void handleChannelConfig(TSD_ChannelConfig *result); - - int getChannelNumber(); - virtual Channel *getChannel(); - virtual Channel *getSecondaryChannel(); - - Element &disableChannelState(); - - protected: - static Element *firstPtr; - Element *nextPtr; -}; - -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _element_h +#define _element_h + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#include +#endif +#include "channel.h" + +namespace Supla { + +class Element { + public: + Element(); + virtual ~Element(); + static Element *begin(); + static Element *last(); + static Element *getElementByChannelNumber(int channelNumber); + Element *next(); + + // method called during SuplaDevice initialization. I.e. load initial state, + // initialize pins etc. + virtual void onInit(); + + // method called during Config initialization (i.e. read from EEPROM, FRAM). + // Called only if Storage class is configured + virtual void onLoadState(); + + // method called periodically during SuplaDevice iteration + // Called only if Storage class is configured + virtual void onSaveState(); + + // method called each time when device successfully registers to server + virtual void onRegistered(); + + // method called on each SuplaDevice iteration (before Network layer + // iteration). When Device is connected, both iterateAlways() and + // iterateConnected() are called. + virtual void iterateAlways(); + + // method called on each Supla::Device iteration when Device is connected and + // registered to Supla server + virtual bool iterateConnected(void *srpc); + + // method called on timer interupt + // Include all actions that have to be executed periodically regardless of + // other SuplaDevice activities + virtual void onTimer(); + + // method called on fast timer interupt + // Include all actions that have to be executed periodically regardless of + // other SuplaDevice activities + virtual void onFastTimer(); + + // return value: + // -1 - don't send reply to server + // 0 - success==false + // 1 - success==true + virtual int handleNewValueFromServer(TSD_SuplaChannelNewValue *newValue); + + // Handles "get channel state" request from server + // channelState is prefilled with network and device status informations + virtual void handleGetChannelState(TDSC_ChannelState &channelState); + + virtual int handleCalcfgFromServer(TSD_DeviceCalCfgRequest *request); + virtual void handleChannelConfig(TSD_ChannelConfig *result); + + int getChannelNumber(); + virtual Channel *getChannel(); + virtual Channel *getSecondaryChannel(); + + Element &disableChannelState(); + + protected: + static Element *firstPtr; + Element *nextPtr; +}; + +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/local_action.cpp b/lib/SuplaDevice/src/supla/local_action.cpp index 61607293..0241796a 100644 --- a/lib/SuplaDevice/src/supla/local_action.cpp +++ b/lib/SuplaDevice/src/supla/local_action.cpp @@ -1,146 +1,146 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "local_action.h" - -namespace Supla { - -class ActionHandlerClient; - -class ActionHandlerClient { - public: - ActionHandlerClient() { - if (begin == nullptr) { - begin = this; - } else { - auto ptr = begin; - while (ptr->next) { - ptr = ptr->next; - } - ptr->next = this; - } - } - - ~ActionHandlerClient() { - if (begin == this) { - begin = next; - return; - } - - auto ptr = begin; - while (ptr->next != this) { - ptr = ptr->next; - } - - ptr->next = ptr->next->next; - } - - LocalAction *trigger = nullptr; - ActionHandler *client = nullptr; - ActionHandlerClient *next = nullptr; - uint8_t onEvent = 0; - uint8_t action = 0; - bool enabled = true; - static ActionHandlerClient *begin; -}; - -ActionHandlerClient *ActionHandlerClient::begin = nullptr; - -LocalAction::~LocalAction() { - auto ptr = ActionHandlerClient::begin; - while (ptr) { - if (ptr->trigger == this) { - auto tbdptr = ptr; - ptr = ptr->next; - if (tbdptr->client->deleteClient()) { - delete tbdptr->client; - } - delete tbdptr; - } else { - ptr = ptr->next; - } - } -} - -void LocalAction::addAction(int action, ActionHandler &client, int event) { - auto ptr = new ActionHandlerClient; - ptr->trigger = this; - ptr->client = &client; - ptr->onEvent = event; - ptr->action = action; - ptr->client->activateAction(action); -} - -void LocalAction::addAction(int action, ActionHandler *client, int event) { - addAction(action, *client, event); -} - -void LocalAction::runAction(int event) { - auto ptr = ActionHandlerClient::begin; - while (ptr) { - if (ptr->trigger == this && ptr->onEvent == event && ptr->enabled) { - ptr->client->handleAction(event, ptr->action); - } - ptr = ptr->next; - } -} - -ActionHandlerClient *LocalAction::getClientListPtr() { - return ActionHandlerClient::begin; -} - -bool LocalAction::isEventAlreadyUsed(int event) { - auto ptr = ActionHandlerClient::begin; - while (ptr) { - if (ptr->trigger == this && ptr->onEvent == event) { - return true; - } - ptr = ptr->next; - } - return false; -} - -void LocalAction::disableOtherClients(ActionHandler &client, int event) { - disableOtherClients(&client, event); -} - -void LocalAction::enableOtherClients(ActionHandler &client, int event) { - enableOtherClients(&client, event); -} - -void LocalAction::disableOtherClients(ActionHandler *client, int event) { - auto ptr = ActionHandlerClient::begin; - while (ptr) { - if (ptr->trigger == this && ptr->onEvent == event && ptr->client != client) { - ptr->enabled = false; - } - ptr = ptr->next; - } - -} - -void LocalAction::enableOtherClients(ActionHandler *client, int event) { - auto ptr = ActionHandlerClient::begin; - while (ptr) { - if (ptr->trigger == this && ptr->onEvent == event && ptr->client != client) { - ptr->enabled = true; - } - ptr = ptr->next; - } - -} - -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "local_action.h" + +namespace Supla { + +class ActionHandlerClient; + +class ActionHandlerClient { + public: + ActionHandlerClient() { + if (begin == nullptr) { + begin = this; + } else { + auto ptr = begin; + while (ptr->next) { + ptr = ptr->next; + } + ptr->next = this; + } + } + + ~ActionHandlerClient() { + if (begin == this) { + begin = next; + return; + } + + auto ptr = begin; + while (ptr->next != this) { + ptr = ptr->next; + } + + ptr->next = ptr->next->next; + } + + LocalAction *trigger = nullptr; + ActionHandler *client = nullptr; + ActionHandlerClient *next = nullptr; + uint8_t onEvent = 0; + uint8_t action = 0; + bool enabled = true; + static ActionHandlerClient *begin; +}; + +ActionHandlerClient *ActionHandlerClient::begin = nullptr; + +LocalAction::~LocalAction() { + auto ptr = ActionHandlerClient::begin; + while (ptr) { + if (ptr->trigger == this) { + auto tbdptr = ptr; + ptr = ptr->next; + if (tbdptr->client->deleteClient()) { + delete tbdptr->client; + } + delete tbdptr; + } else { + ptr = ptr->next; + } + } +} + +void LocalAction::addAction(int action, ActionHandler &client, int event) { + auto ptr = new ActionHandlerClient; + ptr->trigger = this; + ptr->client = &client; + ptr->onEvent = event; + ptr->action = action; + ptr->client->activateAction(action); +} + +void LocalAction::addAction(int action, ActionHandler *client, int event) { + addAction(action, *client, event); +} + +void LocalAction::runAction(int event) { + auto ptr = ActionHandlerClient::begin; + while (ptr) { + if (ptr->trigger == this && ptr->onEvent == event && ptr->enabled) { + ptr->client->handleAction(event, ptr->action); + } + ptr = ptr->next; + } +} + +ActionHandlerClient *LocalAction::getClientListPtr() { + return ActionHandlerClient::begin; +} + +bool LocalAction::isEventAlreadyUsed(int event) { + auto ptr = ActionHandlerClient::begin; + while (ptr) { + if (ptr->trigger == this && ptr->onEvent == event) { + return true; + } + ptr = ptr->next; + } + return false; +} + +void LocalAction::disableOtherClients(ActionHandler &client, int event) { + disableOtherClients(&client, event); +} + +void LocalAction::enableOtherClients(ActionHandler &client, int event) { + enableOtherClients(&client, event); +} + +void LocalAction::disableOtherClients(ActionHandler *client, int event) { + auto ptr = ActionHandlerClient::begin; + while (ptr) { + if (ptr->trigger == this && ptr->onEvent == event && ptr->client != client) { + ptr->enabled = false; + } + ptr = ptr->next; + } + +} + +void LocalAction::enableOtherClients(ActionHandler *client, int event) { + auto ptr = ActionHandlerClient::begin; + while (ptr) { + if (ptr->trigger == this && ptr->onEvent == event && ptr->client != client) { + ptr->enabled = true; + } + ptr = ptr->next; + } + +} + +}; // namespace Supla diff --git a/lib/SuplaDevice/src/supla/local_action.h b/lib/SuplaDevice/src/supla/local_action.h index 5841aeed..8af3c93f 100644 --- a/lib/SuplaDevice/src/supla/local_action.h +++ b/lib/SuplaDevice/src/supla/local_action.h @@ -1,48 +1,48 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _local_action_h -#define _local_action_h - -#include -#include "action_handler.h" - -namespace Supla { - -class ActionHandlerClient; -class Condition; - -class LocalAction { - public: - virtual ~LocalAction(); - virtual void addAction(int action, ActionHandler &client, int event); - virtual void addAction(int action, ActionHandler *client, int event); - - virtual void runAction(int event); - - virtual bool isEventAlreadyUsed(int event); - - virtual void disableOtherClients(ActionHandler &client, int event); - virtual void enableOtherClients(ActionHandler &client, int event); - virtual void disableOtherClients(ActionHandler *client, int event); - virtual void enableOtherClients(ActionHandler *client, int event); - - static ActionHandlerClient *getClientListPtr(); -}; - -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _local_action_h +#define _local_action_h + +#include +#include "action_handler.h" + +namespace Supla { + +class ActionHandlerClient; +class Condition; + +class LocalAction { + public: + virtual ~LocalAction(); + virtual void addAction(int action, ActionHandler &client, int event); + virtual void addAction(int action, ActionHandler *client, int event); + + virtual void runAction(int event); + + virtual bool isEventAlreadyUsed(int event); + + virtual void disableOtherClients(ActionHandler &client, int event); + virtual void enableOtherClients(ActionHandler &client, int event); + virtual void disableOtherClients(ActionHandler *client, int event); + virtual void enableOtherClients(ActionHandler *client, int event); + + static ActionHandlerClient *getClientListPtr(); +}; + +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/network/network.cpp b/lib/SuplaDevice/src/supla/network/network.cpp index aa69ce7e..8541e473 100644 --- a/lib/SuplaDevice/src/supla/network/network.cpp +++ b/lib/SuplaDevice/src/supla/network/network.cpp @@ -1,235 +1,235 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include -#include - -#include "SuplaDevice.h" -#include "supla-common/log.h" -#include "supla-common/srpc.h" -#include "supla/element.h" -#include "supla/network/network.h" - -namespace Supla { - -Network *Network::netIntf = NULL; - -_supla_int_t data_read(void *buf, _supla_int_t count, void *userParams) { - (void)(userParams); - return Supla::Network::Read(buf, count); -} - -_supla_int_t data_write(void *buf, _supla_int_t count, void *userParams) { - (void)(userParams); - _supla_int_t r = Supla::Network::Write(buf, count); - if (r > 0) { - Network::Instance()->updateLastSent(); - } - return r; -} - -void message_received(void *_srpc, - unsigned _supla_int_t rr_id, - unsigned _supla_int_t call_type, - void *_sdc, - unsigned char proto_version) { - (void)(rr_id); - (void)(call_type); - (void)(proto_version); - TsrpcReceivedData rd; - int8_t getDataResult; - - Network::Instance()->updateLastResponse(); - - if (SUPLA_RESULT_TRUE == (getDataResult = srpc_getdata(_srpc, &rd, 0))) { - switch (rd.call_type) { - case SUPLA_SDC_CALL_VERSIONERROR: - ((SuplaDeviceClass *)_sdc)->onVersionError(rd.data.sdc_version_error); - break; - case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: - ((SuplaDeviceClass *)_sdc) - ->onRegisterResult(rd.data.sd_register_device_result); - break; - case SUPLA_SD_CALL_CHANNEL_SET_VALUE: { - auto element = Supla::Element::getElementByChannelNumber( - rd.data.sd_channel_new_value->ChannelNumber); - if (element) { - int actionResult = - element->handleNewValueFromServer(rd.data.sd_channel_new_value); - if (actionResult != -1) { - srpc_ds_async_set_channel_result( - _srpc, - rd.data.sd_channel_new_value->ChannelNumber, - rd.data.sd_channel_new_value->SenderID, - actionResult); - } - } else { - Serial.print(F("Error: couldn't find element for a requested channel [")); - Serial.print(rd.data.sd_channel_new_value->ChannelNumber); - Serial.println(F("]")); - } - break; - } - case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: - ((SuplaDeviceClass *)_sdc) - ->channelSetActivityTimeoutResult( - rd.data.sdc_set_activity_timeout_result); - break; - case SUPLA_CSD_CALL_GET_CHANNEL_STATE: { - TDSC_ChannelState state; - memset(&state, 0, sizeof(TDSC_ChannelState)); - state.ReceiverID = rd.data.csd_channel_state_request->SenderID; - state.ChannelNumber = rd.data.csd_channel_state_request->ChannelNumber; - Network::Instance()->fillStateData(state); - ((SuplaDeviceClass *)_sdc)->fillStateData(state); - auto element = Supla::Element::getElementByChannelNumber( - rd.data.csd_channel_state_request->ChannelNumber); - if (element) { - element->handleGetChannelState(state); - } - srpc_csd_async_channel_state_result(_srpc, &state); - break; - } - case SUPLA_SDC_CALL_PING_SERVER_RESULT: - break; - - case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: { - ((SuplaDeviceClass *)_sdc)->onGetUserLocaltimeResult(rd.data.sdc_user_localtime_result); - break; - } - case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: { - TDS_DeviceCalCfgResult result; - result.ReceiverID = rd.data.sd_device_calcfg_request->SenderID; - result.ChannelNumber = rd.data.sd_device_calcfg_request->ChannelNumber; - result.Command = rd.data.sd_device_calcfg_request->Command; - result.Result = SUPLA_CALCFG_RESULT_NOT_SUPPORTED; - result.DataSize = 0; - - if (rd.data.sd_device_calcfg_request->SuperUserAuthorized != 1) { - result.Result = SUPLA_CALCFG_RESULT_UNAUTHORIZED; - } else { - auto element = Supla::Element::getElementByChannelNumber( - rd.data.sd_device_calcfg_request->ChannelNumber); - if (element) { - result.Result = element->handleCalcfgFromServer(rd.data.sd_device_calcfg_request); - } else { - Serial.print(F("Error: couldn't find element for a requested channel [")); - Serial.print(rd.data.sd_channel_new_value->ChannelNumber); - Serial.println(F("]")); - } - } - - srpc_ds_async_device_calcfg_result(_srpc, &result); - break; - } - case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: { - TSD_ChannelConfig *result = rd.data.sd_channel_config; - if (result) { - auto element = Supla::Element::getElementByChannelNumber( - result->ChannelNumber); - if (element) { - element->handleChannelConfig(result); - } else { - Serial.print(F("Error: couldn't find element for a requested channel [")); - Serial.print(result->ChannelNumber); - Serial.println(F("]")); - } - - - } - break; - } - default: - supla_log(LOG_DEBUG, "Received unknown message from server!"); - break; - } - - srpc_rd_free(&rd); - - } else if (getDataResult == SUPLA_RESULT_DATA_ERROR) { - supla_log(LOG_DEBUG, "DATA ERROR!"); - } -} - -Network::Network(unsigned char *ip) { - lastSentMs = 0; - lastPingTimeMs = 0; - serverActivityTimeoutS = 30; - lastResponseMs = 0; - - netIntf = this; - - if (ip == NULL) { - useLocalIp = false; - } else { - useLocalIp = true; - memcpy(localIp, ip, 4); - } -} - -Network::~Network() { - netIntf = nullptr; -} - -bool Network::iterate() { - return false; -} - -void Network::updateLastSent() { - lastSentMs = millis(); -} - -void Network::updateLastResponse() { - lastResponseMs = millis(); -} - -bool Network::ping(void *srpc) { - _supla_int64_t _millis = millis(); - // If time from last response is longer than "server_activity_timeout + 10 s", - // then inform about failure in communication - if ((_millis - lastResponseMs) / 1000 >= (serverActivityTimeoutS + 10)) { - return false; - } else if (_millis - lastPingTimeMs >= 5000 && - ((_millis - lastResponseMs) / 1000 >= - (serverActivityTimeoutS - 5) || - (_millis - lastSentMs) / 1000 >= (serverActivityTimeoutS - 5))) { - lastPingTimeMs = _millis; - srpc_dcs_async_ping_server(srpc); - } - return true; -} - -void Network::clearTimeCounters() { - _supla_int64_t currentTime = millis(); - lastSentMs = currentTime; - lastResponseMs = currentTime; - lastPingTimeMs = currentTime; -} - -void Network::setActivityTimeout(_supla_int_t activityTimeoutSec) { - serverActivityTimeoutS = activityTimeoutSec; -} - -void Network::setTimeout(int timeoutMs) { - (void)(timeoutMs); - supla_log(LOG_DEBUG, "setTimeout is not implemented for this interface"); -} - -void Network::fillStateData(TDSC_ChannelState &channelState) { - (void)(channelState); - supla_log(LOG_DEBUG, "fillStateData is not implemented for this interface"); -} - -}; // namespace Supla +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include +#include + +#include "SuplaDevice.h" +#include "supla-common/log.h" +#include "supla-common/srpc.h" +#include "supla/element.h" +#include "supla/network/network.h" + +namespace Supla { + +Network *Network::netIntf = NULL; + +_supla_int_t data_read(void *buf, _supla_int_t count, void *userParams) { + (void)(userParams); + return Supla::Network::Read(buf, count); +} + +_supla_int_t data_write(void *buf, _supla_int_t count, void *userParams) { + (void)(userParams); + _supla_int_t r = Supla::Network::Write(buf, count); + if (r > 0) { + Network::Instance()->updateLastSent(); + } + return r; +} + +void message_received(void *_srpc, + unsigned _supla_int_t rr_id, + unsigned _supla_int_t call_type, + void *_sdc, + unsigned char proto_version) { + (void)(rr_id); + (void)(call_type); + (void)(proto_version); + TsrpcReceivedData rd; + int8_t getDataResult; + + Network::Instance()->updateLastResponse(); + + if (SUPLA_RESULT_TRUE == (getDataResult = srpc_getdata(_srpc, &rd, 0))) { + switch (rd.call_type) { + case SUPLA_SDC_CALL_VERSIONERROR: + ((SuplaDeviceClass *)_sdc)->onVersionError(rd.data.sdc_version_error); + break; + case SUPLA_SD_CALL_REGISTER_DEVICE_RESULT: + ((SuplaDeviceClass *)_sdc) + ->onRegisterResult(rd.data.sd_register_device_result); + break; + case SUPLA_SD_CALL_CHANNEL_SET_VALUE: { + auto element = Supla::Element::getElementByChannelNumber( + rd.data.sd_channel_new_value->ChannelNumber); + if (element) { + int actionResult = + element->handleNewValueFromServer(rd.data.sd_channel_new_value); + if (actionResult != -1) { + srpc_ds_async_set_channel_result( + _srpc, + rd.data.sd_channel_new_value->ChannelNumber, + rd.data.sd_channel_new_value->SenderID, + actionResult); + } + } else { + Serial.print(F("Error: couldn't find element for a requested channel [")); + Serial.print(rd.data.sd_channel_new_value->ChannelNumber); + Serial.println(F("]")); + } + break; + } + case SUPLA_SDC_CALL_SET_ACTIVITY_TIMEOUT_RESULT: + ((SuplaDeviceClass *)_sdc) + ->channelSetActivityTimeoutResult( + rd.data.sdc_set_activity_timeout_result); + break; + case SUPLA_CSD_CALL_GET_CHANNEL_STATE: { + TDSC_ChannelState state; + memset(&state, 0, sizeof(TDSC_ChannelState)); + state.ReceiverID = rd.data.csd_channel_state_request->SenderID; + state.ChannelNumber = rd.data.csd_channel_state_request->ChannelNumber; + Network::Instance()->fillStateData(state); + ((SuplaDeviceClass *)_sdc)->fillStateData(state); + auto element = Supla::Element::getElementByChannelNumber( + rd.data.csd_channel_state_request->ChannelNumber); + if (element) { + element->handleGetChannelState(state); + } + srpc_csd_async_channel_state_result(_srpc, &state); + break; + } + case SUPLA_SDC_CALL_PING_SERVER_RESULT: + break; + + case SUPLA_DCS_CALL_GET_USER_LOCALTIME_RESULT: { + ((SuplaDeviceClass *)_sdc)->onGetUserLocaltimeResult(rd.data.sdc_user_localtime_result); + break; + } + case SUPLA_SD_CALL_DEVICE_CALCFG_REQUEST: { + TDS_DeviceCalCfgResult result; + result.ReceiverID = rd.data.sd_device_calcfg_request->SenderID; + result.ChannelNumber = rd.data.sd_device_calcfg_request->ChannelNumber; + result.Command = rd.data.sd_device_calcfg_request->Command; + result.Result = SUPLA_CALCFG_RESULT_NOT_SUPPORTED; + result.DataSize = 0; + + if (rd.data.sd_device_calcfg_request->SuperUserAuthorized != 1) { + result.Result = SUPLA_CALCFG_RESULT_UNAUTHORIZED; + } else { + auto element = Supla::Element::getElementByChannelNumber( + rd.data.sd_device_calcfg_request->ChannelNumber); + if (element) { + result.Result = element->handleCalcfgFromServer(rd.data.sd_device_calcfg_request); + } else { + Serial.print(F("Error: couldn't find element for a requested channel [")); + Serial.print(rd.data.sd_channel_new_value->ChannelNumber); + Serial.println(F("]")); + } + } + + srpc_ds_async_device_calcfg_result(_srpc, &result); + break; + } + case SUPLA_SD_CALL_GET_CHANNEL_CONFIG_RESULT: { + TSD_ChannelConfig *result = rd.data.sd_channel_config; + if (result) { + auto element = Supla::Element::getElementByChannelNumber( + result->ChannelNumber); + if (element) { + element->handleChannelConfig(result); + } else { + Serial.print(F("Error: couldn't find element for a requested channel [")); + Serial.print(result->ChannelNumber); + Serial.println(F("]")); + } + + + } + break; + } + default: + supla_log(LOG_DEBUG, "Received unknown message from server!"); + break; + } + + srpc_rd_free(&rd); + + } else if (getDataResult == SUPLA_RESULT_DATA_ERROR) { + supla_log(LOG_DEBUG, "DATA ERROR!"); + } +} + +Network::Network(unsigned char *ip) { + lastSentMs = 0; + lastPingTimeMs = 0; + serverActivityTimeoutS = 30; + lastResponseMs = 0; + + netIntf = this; + + if (ip == NULL) { + useLocalIp = false; + } else { + useLocalIp = true; + memcpy(localIp, ip, 4); + } +} + +Network::~Network() { + netIntf = nullptr; +} + +bool Network::iterate() { + return false; +} + +void Network::updateLastSent() { + lastSentMs = millis(); +} + +void Network::updateLastResponse() { + lastResponseMs = millis(); +} + +bool Network::ping(void *srpc) { + _supla_int64_t _millis = millis(); + // If time from last response is longer than "server_activity_timeout + 10 s", + // then inform about failure in communication + if ((_millis - lastResponseMs) / 1000 >= (serverActivityTimeoutS + 10)) { + return false; + } else if (_millis - lastPingTimeMs >= 5000 && + ((_millis - lastResponseMs) / 1000 >= + (serverActivityTimeoutS - 5) || + (_millis - lastSentMs) / 1000 >= (serverActivityTimeoutS - 5))) { + lastPingTimeMs = _millis; + srpc_dcs_async_ping_server(srpc); + } + return true; +} + +void Network::clearTimeCounters() { + _supla_int64_t currentTime = millis(); + lastSentMs = currentTime; + lastResponseMs = currentTime; + lastPingTimeMs = currentTime; +} + +void Network::setActivityTimeout(_supla_int_t activityTimeoutSec) { + serverActivityTimeoutS = activityTimeoutSec; +} + +void Network::setTimeout(int timeoutMs) { + (void)(timeoutMs); + supla_log(LOG_DEBUG, "setTimeout is not implemented for this interface"); +} + +void Network::fillStateData(TDSC_ChannelState &channelState) { + (void)(channelState); + supla_log(LOG_DEBUG, "fillStateData is not implemented for this interface"); +} + +}; // namespace Supla diff --git a/lib/SuplaDevice/src/supla/pv/solaredge.cpp b/lib/SuplaDevice/src/supla/pv/solaredge.cpp index d4b178bf..a9b78884 100644 --- a/lib/SuplaDevice/src/supla/pv/solaredge.cpp +++ b/lib/SuplaDevice/src/supla/pv/solaredge.cpp @@ -1,386 +1,386 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef ARDUINO_ARCH_AVR -#include "solaredge.h" - -#define TEMPERATURE_NOT_AVAILABLE -275.0 - -using namespace Supla; -using namespace PV; - -// This header should be received from server when data is returned -// It will be verified with actual header if they match. Otherwise, data structure is assumed to be changed -// and it will require this file to be adjusted to support new format -const char headerVerification[] = "date,inverterMode,temperature,totalActivePower,dcVoltage,groundFaultResistance,powerLimit,totalEnergy,vL1To2,vL2To3,vL3To1,L1-acCurrent,L1-acVoltage,L1-acFrequency,L1-apparentPower,L1-activePower,L1-reactivePower,L1-qRef,L1-cosPhi,L2-acCurrent,L2-acVoltage,L2-acFrequency,L2-apparentPower,L2-activePower,L2-reactivePower,L2-qRef,L2-cosPhi,L3-acCurrent,L3-acVoltage,L3-acFrequency,L3-apparentPower,L3-activePower,L3-reactivePower,L3-qRef,L3-cosPhi"; - -SolarEdge::SolarEdge(const char *apiKeyValue, const char *siteIdValue, const char *inverterSerialNumberValue, Supla::Clock *clock) : - buf{}, - temperature(TEMPERATURE_NOT_AVAILABLE), - totalGeneratedEnergy(0), - currentCurrent{}, - currentVoltage{}, - currentFreq(0), - currentApparentPower{}, - currentActivePower{}, - currentReactivePower{}, - bytesCounter(0), - retryCounter(0), - dataIsReady(false), - dataFetchInProgress(false), - headerFound(false), - connectionTimeoutMs(0), - clock(clock) -{ - // SolarEdge api allows 300 requests daily, so it is one request per almost 5 min - refreshRateSec = 6*60; // refresh every 6 min - - int len = strlen(apiKeyValue); - if (len > APIKEY_MAX_LENGTH) { - len = APIKEY_MAX_LENGTH; - } - strncpy(apiKey, apiKeyValue, len); - - len = strlen(siteIdValue); - if (len > PARAMETER_MAX_LENGTH) { - len = PARAMETER_MAX_LENGTH; - } - strncpy(siteId, siteIdValue, len); - - len = strlen(inverterSerialNumberValue); - if (len > PARAMETER_MAX_LENGTH) { - len = PARAMETER_MAX_LENGTH; - } - strncpy(inverterSerialNumber, inverterSerialNumberValue, len); - - temperatureChannel.setType(SUPLA_CHANNELTYPE_THERMOMETER); - temperatureChannel.setDefault(SUPLA_CHANNELFNC_THERMOMETER); - temperatureChannel.setNewValue(TEMPERATURE_NOT_AVAILABLE); -} - -void SolarEdge::iterateAlways() { - if (dataFetchInProgress) { - if (millis() - connectionTimeoutMs > 30000) { - Serial.println(F("SolarEdge: connection timeout. Remote host is not responding")); - pvClient.stop(); - dataFetchInProgress = false; - dataIsReady = false; - return; - } - if (!pvClient.connected()) { - Serial.println(F("SolarEdge fetch completed")); - dataFetchInProgress = false; - dataIsReady = true; - } - if (pvClient.available()) { - Serial.print(F("Reading data from SolarEdge: ")); - Serial.println(pvClient.available()); - } - while (pvClient.available()) { - char c; - c = pvClient.read(); - Serial.print(c); - if (c == '\n') { - if (bytesCounter > 0) { - // new line is found with bytesCounter > 0 means that we have full received line of data in buf - buf[bytesCounter] = '\0'; // add null character at the end of received string - - if (!headerFound) { - if (0 == strncmp(headerVerification, buf, sizeof(headerVerification)-1)) { - headerFound = true; - } - } else { - int commaCount = 0; - for (unsigned int i = 0; i < strlen(buf); i++) { - if (buf[i] == ',') commaCount++; - } - // proper line of data should contain at least 34 commas - if (commaCount >= 34) { - strtok(buf, ","); - for (int i = 1; i < 34; i++) { - char *value = strtok(nullptr, ","); - /* -0 date, -1 inverterMode, -2 temperature, -3 totalActivePower, -4 dcVoltage, -5 groundFaultResistance, -6 powerLimit, -7 totalEnergy, -8 vL1To2, -9 vL2To3, -10 vL3To1, -11 L1-acCurrent, -12 L1-acVoltage, -13 L1-acFrequency, -14 L1-apparentPower, -15 L1-activePower, -16 L1-reactivePower, -17 L1-qRef, -18 L1-cosPhi, -19 L2-acCurrent, -20 L2-acVoltage, -21 L2-acFrequency, -22 L2-apparentPower, -23 L2-activePower, -24 L2-reactivePower, -25 L2-qRef, -26 L2-cosPhi, -27 L3-acCurrent, -28 L3-acVoltage, -29 L3-acFrequency, -30 L3-apparentPower, -31 L3-activePower, -32 L3-reactivePower, -33 L3-qRef, -34 L3-cosPhi -*/ - switch (i) { - case 1: { // inverterMode - if (strncmp(value, "MPPT", 4) != 0) { - // ignoring data for inverter in mode other than MPPT - i = commaCount; - } - break; - } - case 2: { // temperature - temperature = atof(value); - break; - } - case 7: { // totalEnergy - split per 3 phases - double energy = atof(value); - totalGeneratedEnergy = energy * 100; - break; - } - case 11: { // L1 - acCurrent - double current = atof(value); - currentCurrent[0] = current * 1000; - break; - } - case 12: { // L1 - acVoltage - double voltage = atof(value); - currentVoltage[0] = voltage * 100; - break; - } - case 13: { // L1 - acFrequency - double frequency = atof(value); - currentFreq = frequency * 100; - break; - } - case 14: { // L1 - apparentPower - double power = atof(value); - currentApparentPower[0] = power * 100000; - break; - } - case 15: { // L1 - activePower - double power = atof(value); - currentActivePower[0] = power * 100000; - break; - } - case 16: { // L1 - ReactivePower - double power = atof(value); - currentReactivePower[0] = power * 100000; - break; - } - case 19: { // L2 - acCurrent - double current = atof(value); // Wh - currentCurrent[1] = current * 1000; - break; - } - case 20: { // L2 - acVoltage - double voltage = atof(value); // Wh - currentVoltage[1] = voltage * 100; - break; - } - case 22: { // L2 - apparentPower - double power = atof(value); - currentApparentPower[1] = power * 100000; - break; - } - case 23: { // L2 - activePower - double power = atof(value); - currentActivePower[1] = power * 100000; - break; - } - case 24: { // L2 - ReactivePower - double power = atof(value); - currentReactivePower[1] = power * 100000; - break; - } - case 27: { // L3 - acCurrent - double current = atof(value); // Wh - currentCurrent[2] = current * 1000; - break; - } - case 28: { // L3 - acVoltage - double voltage = atof(value); // Wh - currentVoltage[2] = voltage * 100; - break; - } - case 30: { // L3 - apparentPower - double power = atof(value); - currentApparentPower[2] = power * 100000; - break; - } - case 31: { // L3 - activePower - double power = atof(value); - currentActivePower[2] = power * 100000; - break; - } - case 32: { // L3 - ReactivePower - double power = atof(value); - currentReactivePower[2] = power * 100000; - break; - } - // acCurrent setCurrent - // acVoltage - // acFreq - // apparentPower - // activePower - // ReactivePower - - } - } - } - - } - - } - bytesCounter = 0; - } else if (bytesCounter < 1023) { - buf[bytesCounter] = c; - bytesCounter++; - } - } - if (!pvClient.connected()) { - pvClient.stop(); - } - } - if (dataIsReady) { - dataIsReady = false; - headerFound = false; - for (int i = 0; i < 3; i++) { - if (totalGeneratedEnergy > 0) { - setFwdActEnergy(i, totalGeneratedEnergy/3.0); - } - setPowerActive(i, currentActivePower[i]); - currentActivePower[i] = 0; - setCurrent(i, currentCurrent[i]); - currentCurrent[i] = 0; - setVoltage(i, currentVoltage[i]); - currentVoltage[i] = 0; - setPowerApparent(i, currentApparentPower[i]); - currentApparentPower[i] = 0; - setPowerReactive(i, currentReactivePower[i]); - currentReactivePower[i] = 0; - } - totalGeneratedEnergy = 0; - setFreq(1); - setFreq(currentFreq); - currentFreq = 0; - temperatureChannel.setNewValue(temperature); - temperature = TEMPERATURE_NOT_AVAILABLE; - updateChannelValues(); - } -} - -bool SolarEdge::iterateConnected(void *srpc) { - if (clock && clock->isReady()) { - if (!dataFetchInProgress) { - bytesCounter = 0; - if (lastReadTime == 0 || millis() - lastReadTime > (retryCounter > 0 ? 5000 : refreshRateSec*1000)) { - lastReadTime = millis(); - Serial.println(F("SolarEdge connecting")); -#ifdef ARDUINO_ARCH_ESP8266 - pvClient.setBufferSizes(2048, 512); // -#endif - pvClient.setInsecure(); - int returnCode = pvClient.connect("monitoringapi.solaredge.com", 443); - if (returnCode) { - retryCounter = 0; - dataFetchInProgress = true; - connectionTimeoutMs = lastReadTime; - Serial.println(F("Succesful connect")); - - char buf[200]; - strcpy(buf, "GET /equipment/"); - - strcat(buf, siteId); - strcat(buf, "/"); - strcat(buf, inverterSerialNumber); - strcat(buf, "/data.csv?startTime="); - - time_t timestamp = time(0); // get current time - timestamp -= 10*60; // go back in time 10 minutes - -#define SOLAR_TMP_BUFFER_SIZE 100 - - char startTime[SOLAR_TMP_BUFFER_SIZE]; - char endTime[SOLAR_TMP_BUFFER_SIZE]; - - struct tm timeinfo; - gmtime_r(×tamp, &timeinfo); - - snprintf(startTime, - SOLAR_TMP_BUFFER_SIZE, - "%d-%d-%d%%20%d:%d:%d", - timeinfo.tm_year + 1900, - timeinfo.tm_mon + 1, - timeinfo.tm_mday, - timeinfo.tm_hour, - timeinfo.tm_min, - timeinfo.tm_sec); - snprintf(endTime, - SOLAR_TMP_BUFFER_SIZE, - "%d-%d-%d%%2023:59:59", - timeinfo.tm_year + 1900, - timeinfo.tm_mon + 1, - timeinfo.tm_mday); - - strcat(buf, startTime); - strcat(buf, "&endTime="); - strcat(buf, endTime); - strcat(buf, "&api_key="); - strcat(buf, apiKey); - strcat(buf, " HTTP/1.1"); - - Serial.print(F("Query: ")); - Serial.println(buf); - pvClient.println(buf); - pvClient.println(F("Host: localhost")); - pvClient.println(F("Connection: close")); - pvClient.println(); - - } else { // if connection wasn't successful, try few times - Serial.print(F("Failed to connect to SolarEdge api, return code: ")); - Serial.println(returnCode); - retryCounter++; - } - } - } - } - return Element::iterateConnected(srpc); -} - -void SolarEdge::readValuesFromDevice() { -} - -Supla::Channel *SolarEdge::getSecondaryChannel() { - return &temperatureChannel; -} - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef ARDUINO_ARCH_AVR +#include "solaredge.h" + +#define TEMPERATURE_NOT_AVAILABLE -275.0 + +using namespace Supla; +using namespace PV; + +// This header should be received from server when data is returned +// It will be verified with actual header if they match. Otherwise, data structure is assumed to be changed +// and it will require this file to be adjusted to support new format +const char headerVerification[] = "date,inverterMode,temperature,totalActivePower,dcVoltage,groundFaultResistance,powerLimit,totalEnergy,vL1To2,vL2To3,vL3To1,L1-acCurrent,L1-acVoltage,L1-acFrequency,L1-apparentPower,L1-activePower,L1-reactivePower,L1-qRef,L1-cosPhi,L2-acCurrent,L2-acVoltage,L2-acFrequency,L2-apparentPower,L2-activePower,L2-reactivePower,L2-qRef,L2-cosPhi,L3-acCurrent,L3-acVoltage,L3-acFrequency,L3-apparentPower,L3-activePower,L3-reactivePower,L3-qRef,L3-cosPhi"; + +SolarEdge::SolarEdge(const char *apiKeyValue, const char *siteIdValue, const char *inverterSerialNumberValue, Supla::Clock *clock) : + buf{}, + temperature(TEMPERATURE_NOT_AVAILABLE), + totalGeneratedEnergy(0), + currentCurrent{}, + currentVoltage{}, + currentFreq(0), + currentApparentPower{}, + currentActivePower{}, + currentReactivePower{}, + bytesCounter(0), + retryCounter(0), + dataIsReady(false), + dataFetchInProgress(false), + headerFound(false), + connectionTimeoutMs(0), + clock(clock) +{ + // SolarEdge api allows 300 requests daily, so it is one request per almost 5 min + refreshRateSec = 6*60; // refresh every 6 min + + int len = strlen(apiKeyValue); + if (len > APIKEY_MAX_LENGTH) { + len = APIKEY_MAX_LENGTH; + } + strncpy(apiKey, apiKeyValue, len); + + len = strlen(siteIdValue); + if (len > PARAMETER_MAX_LENGTH) { + len = PARAMETER_MAX_LENGTH; + } + strncpy(siteId, siteIdValue, len); + + len = strlen(inverterSerialNumberValue); + if (len > PARAMETER_MAX_LENGTH) { + len = PARAMETER_MAX_LENGTH; + } + strncpy(inverterSerialNumber, inverterSerialNumberValue, len); + + temperatureChannel.setType(SUPLA_CHANNELTYPE_THERMOMETER); + temperatureChannel.setDefault(SUPLA_CHANNELFNC_THERMOMETER); + temperatureChannel.setNewValue(TEMPERATURE_NOT_AVAILABLE); +} + +void SolarEdge::iterateAlways() { + if (dataFetchInProgress) { + if (millis() - connectionTimeoutMs > 30000) { + Serial.println(F("SolarEdge: connection timeout. Remote host is not responding")); + pvClient.stop(); + dataFetchInProgress = false; + dataIsReady = false; + return; + } + if (!pvClient.connected()) { + Serial.println(F("SolarEdge fetch completed")); + dataFetchInProgress = false; + dataIsReady = true; + } + if (pvClient.available()) { + Serial.print(F("Reading data from SolarEdge: ")); + Serial.println(pvClient.available()); + } + while (pvClient.available()) { + char c; + c = pvClient.read(); + Serial.print(c); + if (c == '\n') { + if (bytesCounter > 0) { + // new line is found with bytesCounter > 0 means that we have full received line of data in buf + buf[bytesCounter] = '\0'; // add null character at the end of received string + + if (!headerFound) { + if (0 == strncmp(headerVerification, buf, sizeof(headerVerification)-1)) { + headerFound = true; + } + } else { + int commaCount = 0; + for (unsigned int i = 0; i < strlen(buf); i++) { + if (buf[i] == ',') commaCount++; + } + // proper line of data should contain at least 34 commas + if (commaCount >= 34) { + strtok(buf, ","); + for (int i = 1; i < 34; i++) { + char *value = strtok(nullptr, ","); + /* +0 date, +1 inverterMode, +2 temperature, +3 totalActivePower, +4 dcVoltage, +5 groundFaultResistance, +6 powerLimit, +7 totalEnergy, +8 vL1To2, +9 vL2To3, +10 vL3To1, +11 L1-acCurrent, +12 L1-acVoltage, +13 L1-acFrequency, +14 L1-apparentPower, +15 L1-activePower, +16 L1-reactivePower, +17 L1-qRef, +18 L1-cosPhi, +19 L2-acCurrent, +20 L2-acVoltage, +21 L2-acFrequency, +22 L2-apparentPower, +23 L2-activePower, +24 L2-reactivePower, +25 L2-qRef, +26 L2-cosPhi, +27 L3-acCurrent, +28 L3-acVoltage, +29 L3-acFrequency, +30 L3-apparentPower, +31 L3-activePower, +32 L3-reactivePower, +33 L3-qRef, +34 L3-cosPhi +*/ + switch (i) { + case 1: { // inverterMode + if (strncmp(value, "MPPT", 4) != 0) { + // ignoring data for inverter in mode other than MPPT + i = commaCount; + } + break; + } + case 2: { // temperature + temperature = atof(value); + break; + } + case 7: { // totalEnergy - split per 3 phases + double energy = atof(value); + totalGeneratedEnergy = energy * 100; + break; + } + case 11: { // L1 - acCurrent + double current = atof(value); + currentCurrent[0] = current * 1000; + break; + } + case 12: { // L1 - acVoltage + double voltage = atof(value); + currentVoltage[0] = voltage * 100; + break; + } + case 13: { // L1 - acFrequency + double frequency = atof(value); + currentFreq = frequency * 100; + break; + } + case 14: { // L1 - apparentPower + double power = atof(value); + currentApparentPower[0] = power * 100000; + break; + } + case 15: { // L1 - activePower + double power = atof(value); + currentActivePower[0] = power * 100000; + break; + } + case 16: { // L1 - ReactivePower + double power = atof(value); + currentReactivePower[0] = power * 100000; + break; + } + case 19: { // L2 - acCurrent + double current = atof(value); // Wh + currentCurrent[1] = current * 1000; + break; + } + case 20: { // L2 - acVoltage + double voltage = atof(value); // Wh + currentVoltage[1] = voltage * 100; + break; + } + case 22: { // L2 - apparentPower + double power = atof(value); + currentApparentPower[1] = power * 100000; + break; + } + case 23: { // L2 - activePower + double power = atof(value); + currentActivePower[1] = power * 100000; + break; + } + case 24: { // L2 - ReactivePower + double power = atof(value); + currentReactivePower[1] = power * 100000; + break; + } + case 27: { // L3 - acCurrent + double current = atof(value); // Wh + currentCurrent[2] = current * 1000; + break; + } + case 28: { // L3 - acVoltage + double voltage = atof(value); // Wh + currentVoltage[2] = voltage * 100; + break; + } + case 30: { // L3 - apparentPower + double power = atof(value); + currentApparentPower[2] = power * 100000; + break; + } + case 31: { // L3 - activePower + double power = atof(value); + currentActivePower[2] = power * 100000; + break; + } + case 32: { // L3 - ReactivePower + double power = atof(value); + currentReactivePower[2] = power * 100000; + break; + } + // acCurrent setCurrent + // acVoltage + // acFreq + // apparentPower + // activePower + // ReactivePower + + } + } + } + + } + + } + bytesCounter = 0; + } else if (bytesCounter < 1023) { + buf[bytesCounter] = c; + bytesCounter++; + } + } + if (!pvClient.connected()) { + pvClient.stop(); + } + } + if (dataIsReady) { + dataIsReady = false; + headerFound = false; + for (int i = 0; i < 3; i++) { + if (totalGeneratedEnergy > 0) { + setFwdActEnergy(i, totalGeneratedEnergy/3.0); + } + setPowerActive(i, currentActivePower[i]); + currentActivePower[i] = 0; + setCurrent(i, currentCurrent[i]); + currentCurrent[i] = 0; + setVoltage(i, currentVoltage[i]); + currentVoltage[i] = 0; + setPowerApparent(i, currentApparentPower[i]); + currentApparentPower[i] = 0; + setPowerReactive(i, currentReactivePower[i]); + currentReactivePower[i] = 0; + } + totalGeneratedEnergy = 0; + setFreq(1); + setFreq(currentFreq); + currentFreq = 0; + temperatureChannel.setNewValue(temperature); + temperature = TEMPERATURE_NOT_AVAILABLE; + updateChannelValues(); + } +} + +bool SolarEdge::iterateConnected(void *srpc) { + if (clock && clock->isReady()) { + if (!dataFetchInProgress) { + bytesCounter = 0; + if (lastReadTime == 0 || millis() - lastReadTime > (retryCounter > 0 ? 5000 : refreshRateSec*1000)) { + lastReadTime = millis(); + Serial.println(F("SolarEdge connecting")); +#ifdef ARDUINO_ARCH_ESP8266 + pvClient.setBufferSizes(2048, 512); // +#endif + pvClient.setInsecure(); + int returnCode = pvClient.connect("monitoringapi.solaredge.com", 443); + if (returnCode) { + retryCounter = 0; + dataFetchInProgress = true; + connectionTimeoutMs = lastReadTime; + Serial.println(F("Succesful connect")); + + char buf[200]; + strcpy(buf, "GET /equipment/"); + + strcat(buf, siteId); + strcat(buf, "/"); + strcat(buf, inverterSerialNumber); + strcat(buf, "/data.csv?startTime="); + + time_t timestamp = time(0); // get current time + timestamp -= 10*60; // go back in time 10 minutes + +#define SOLAR_TMP_BUFFER_SIZE 100 + + char startTime[SOLAR_TMP_BUFFER_SIZE]; + char endTime[SOLAR_TMP_BUFFER_SIZE]; + + struct tm timeinfo; + gmtime_r(×tamp, &timeinfo); + + snprintf(startTime, + SOLAR_TMP_BUFFER_SIZE, + "%d-%d-%d%%20%d:%d:%d", + timeinfo.tm_year + 1900, + timeinfo.tm_mon + 1, + timeinfo.tm_mday, + timeinfo.tm_hour, + timeinfo.tm_min, + timeinfo.tm_sec); + snprintf(endTime, + SOLAR_TMP_BUFFER_SIZE, + "%d-%d-%d%%2023:59:59", + timeinfo.tm_year + 1900, + timeinfo.tm_mon + 1, + timeinfo.tm_mday); + + strcat(buf, startTime); + strcat(buf, "&endTime="); + strcat(buf, endTime); + strcat(buf, "&api_key="); + strcat(buf, apiKey); + strcat(buf, " HTTP/1.1"); + + Serial.print(F("Query: ")); + Serial.println(buf); + pvClient.println(buf); + pvClient.println(F("Host: localhost")); + pvClient.println(F("Connection: close")); + pvClient.println(); + + } else { // if connection wasn't successful, try few times + Serial.print(F("Failed to connect to SolarEdge api, return code: ")); + Serial.println(returnCode); + retryCounter++; + } + } + } + } + return Element::iterateConnected(srpc); +} + +void SolarEdge::readValuesFromDevice() { +} + +Supla::Channel *SolarEdge::getSecondaryChannel() { + return &temperatureChannel; +} + +#endif diff --git a/lib/SuplaDevice/src/supla/sensor/SHT3x.h b/lib/SuplaDevice/src/supla/sensor/SHT3x.h index 3406ac14..87b73fab 100644 --- a/lib/SuplaDevice/src/supla/sensor/SHT3x.h +++ b/lib/SuplaDevice/src/supla/sensor/SHT3x.h @@ -1,93 +1,93 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _sht3x_h -#define _sht3x_h - -// Dependency: ClosedCube SHT3x library - use library manager to install it -// https://github.com/closedcube/ClosedCube_SHT31D_Arduino - -#include - -#include "therm_hygro_meter.h" - - -namespace Supla { -namespace Sensor { -class SHT3x : public ThermHygroMeter { - public: - SHT3x(int8_t address = 0x44) - : temperature(TEMPERATURE_NOT_AVAILABLE), - humidity(HUMIDITY_NOT_AVAILABLE), - address(address), - retryCount(0) { - } - - double getTemp() { - return temperature; - } - - double getHumi() { - return humidity; - } - - private: - void iterateAlways() { - if (millis() - lastReadTime > 10000) { - lastReadTime = millis(); - readValuesFromDevice(); - channel.setNewValue(getTemp(), getHumi()); - } - } - - void onInit() { - sht.begin(address); - readValuesFromDevice(); - channel.setNewValue(getTemp(), getHumi()); - } - - void readValuesFromDevice() { - SHT31D result = sht.readTempAndHumidity( - SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50); - - if (result.error != SHT3XD_NO_ERROR) { - Serial.print(F("SHT [ERROR] Code #")); - Serial.println(result.error); - retryCount++; - if (retryCount > 3) { - retryCount = 0; - temperature = TEMPERATURE_NOT_AVAILABLE; - humidity = HUMIDITY_NOT_AVAILABLE; - } - } else { - retryCount = 0; - temperature = result.t; - humidity = result.rh; - } - } - - protected: - int8_t address; - double temperature; - double humidity; - int8_t retryCount; - ::ClosedCube_SHT31D sht; // I2C -}; - -}; // namespace Sensor -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _sht3x_h +#define _sht3x_h + +// Dependency: ClosedCube SHT3x library - use library manager to install it +// https://github.com/closedcube/ClosedCube_SHT31D_Arduino + +#include + +#include "therm_hygro_meter.h" + + +namespace Supla { +namespace Sensor { +class SHT3x : public ThermHygroMeter { + public: + SHT3x(int8_t address = 0x44) + : temperature(TEMPERATURE_NOT_AVAILABLE), + humidity(HUMIDITY_NOT_AVAILABLE), + address(address), + retryCount(0) { + } + + double getTemp() { + return temperature; + } + + double getHumi() { + return humidity; + } + + private: + void iterateAlways() { + if (millis() - lastReadTime > 10000) { + lastReadTime = millis(); + readValuesFromDevice(); + channel.setNewValue(getTemp(), getHumi()); + } + } + + void onInit() { + sht.begin(address); + readValuesFromDevice(); + channel.setNewValue(getTemp(), getHumi()); + } + + void readValuesFromDevice() { + SHT31D result = sht.readTempAndHumidity( + SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50); + + if (result.error != SHT3XD_NO_ERROR) { + Serial.print(F("SHT [ERROR] Code #")); + Serial.println(result.error); + retryCount++; + if (retryCount > 3) { + retryCount = 0; + temperature = TEMPERATURE_NOT_AVAILABLE; + humidity = HUMIDITY_NOT_AVAILABLE; + } + } else { + retryCount = 0; + temperature = result.t; + humidity = result.rh; + } + } + + protected: + int8_t address; + double temperature; + double humidity; + int8_t retryCount; + ::ClosedCube_SHT31D sht; // I2C +}; + +}; // namespace Sensor +}; // namespace Supla + +#endif diff --git a/lib/SuplaDevice/src/supla/sensor/electricity_meter.cpp b/lib/SuplaDevice/src/supla/sensor/electricity_meter.cpp index 3a5a8291..d9fa8860 100644 --- a/lib/SuplaDevice/src/supla/sensor/electricity_meter.cpp +++ b/lib/SuplaDevice/src/supla/sensor/electricity_meter.cpp @@ -1,274 +1,274 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include "electricity_meter.h" -#include "../events.h" -#include "../condition.h" - -Supla::Sensor::ElectricityMeter::ElectricityMeter() - : valueChanged(false), lastReadTime(0), refreshRateSec(5) { - extChannel.setType(SUPLA_CHANNELTYPE_ELECTRICITY_METER); - extChannel.setDefault(SUPLA_CHANNELFNC_ELECTRICITY_METER); - memset(&emValue, 0, sizeof(emValue)); - emValue.period = 5; - for (int i = 0; i < MAX_PHASES; i++) { - rawCurrent[i] = 0; - } - currentMeasurementAvailable = false; -} - -void Supla::Sensor::ElectricityMeter::updateChannelValues() { - if (!valueChanged) { - return; - } - valueChanged = false; - - emValue.m_count = 1; - - // Update current messurement precision based on last updates - if (currentMeasurementAvailable) { - bool over65A = false; - for (int i = 0; i < MAX_PHASES; i++) { - if (rawCurrent[i] > 65000) { - over65A = true; - } - } - - for (int i = 0; i < MAX_PHASES; i++) { - if (over65A) { - emValue.m[0].current[i] = rawCurrent[i] / 10; - } else { - emValue.m[0].current[i] = rawCurrent[i]; - } - } - - if (over65A) { - emValue.measured_values &= (!EM_VAR_CURRENT); - emValue.measured_values |= EM_VAR_CURRENT_OVER_65A; - } else { - emValue.measured_values &= (!EM_VAR_CURRENT_OVER_65A); - emValue.measured_values |= EM_VAR_CURRENT; - } - } - - // Prepare extended channel value - srpc_evtool_v2_emextended2extended(&emValue, extChannel.getExtValue()); - extChannel.setNewValue(emValue); - runAction(Supla::ON_CHANGE); -} - -// energy in 0.00001 kWh -void Supla::Sensor::ElectricityMeter::setFwdActEnergy( - int phase, unsigned _supla_int64_t energy) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.total_forward_active_energy[phase] != energy) { - valueChanged = true; - } - emValue.total_forward_active_energy[phase] = energy; - emValue.measured_values |= EM_VAR_FORWARD_ACTIVE_ENERGY; - } -} - -// energy in 0.00001 kWh -void Supla::Sensor::ElectricityMeter::setRvrActEnergy( - int phase, unsigned _supla_int64_t energy) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.total_reverse_active_energy[phase] != energy) { - valueChanged = true; - } - emValue.total_reverse_active_energy[phase] = energy; - emValue.measured_values |= EM_VAR_REVERSE_ACTIVE_ENERGY; - } -} - -// energy in 0.00001 kWh -void Supla::Sensor::ElectricityMeter::setFwdReactEnergy( - int phase, unsigned _supla_int64_t energy) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.total_forward_reactive_energy[phase] != energy) { - valueChanged = true; - } - emValue.total_forward_reactive_energy[phase] = energy; - emValue.measured_values |= EM_VAR_FORWARD_REACTIVE_ENERGY; - } -} - -// energy in 0.00001 kWh -void Supla::Sensor::ElectricityMeter::setRvrReactEnergy( - int phase, unsigned _supla_int64_t energy) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.total_reverse_reactive_energy[phase] != energy) { - valueChanged = true; - } - emValue.total_reverse_reactive_energy[phase] = energy; - emValue.measured_values |= EM_VAR_REVERSE_REACTIVE_ENERGY; - } -} - -// voltage in 0.01 V -void Supla::Sensor::ElectricityMeter::setVoltage( - int phase, unsigned _supla_int16_t voltage) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].voltage[phase] != voltage) { - valueChanged = true; - } - emValue.m[0].voltage[phase] = voltage; - emValue.measured_values |= EM_VAR_VOLTAGE; - } -} - -// current in 0.001 A -void Supla::Sensor::ElectricityMeter::setCurrent( - int phase, unsigned _supla_int_t current) { - if (phase >= 0 && phase < MAX_PHASES) { - if (rawCurrent[phase] != current) { - valueChanged = true; - } - rawCurrent[phase] = current; - currentMeasurementAvailable = true; - } -} - -// Frequency in 0.01 Hz -void Supla::Sensor::ElectricityMeter::setFreq(unsigned _supla_int16_t freq) { - if (emValue.m[0].freq != freq) { - valueChanged = true; - } - emValue.m[0].freq = freq; - emValue.measured_values |= EM_VAR_FREQ; -} - -// power in 0.00001 kW -void Supla::Sensor::ElectricityMeter::setPowerActive(int phase, - _supla_int_t power) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].power_active[phase] != power) { - valueChanged = true; - } - emValue.m[0].power_active[phase] = power; - emValue.measured_values |= EM_VAR_POWER_ACTIVE; - } -} - -// power in 0.00001 kvar -void Supla::Sensor::ElectricityMeter::setPowerReactive(int phase, - _supla_int_t power) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].power_reactive[phase] != power) { - valueChanged = true; - } - emValue.m[0].power_reactive[phase] = power; - emValue.measured_values |= EM_VAR_POWER_REACTIVE; - } -} - -// power in 0.00001 kVA -void Supla::Sensor::ElectricityMeter::setPowerApparent(int phase, - _supla_int_t power) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].power_apparent[phase] != power) { - valueChanged = true; - } - emValue.m[0].power_apparent[phase] = power; - emValue.measured_values |= EM_VAR_POWER_APPARENT; - } -} - -// power in 0.001 -void Supla::Sensor::ElectricityMeter::setPowerFactor(int phase, - _supla_int_t powerFactor) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].power_factor[phase] != powerFactor) { - valueChanged = true; - } - emValue.m[0].power_factor[phase] = powerFactor; - emValue.measured_values |= EM_VAR_POWER_FACTOR; - } -} - -// phase angle in 0.1 degree -void Supla::Sensor::ElectricityMeter::setPhaseAngle(int phase, - _supla_int_t phaseAngle) { - if (phase >= 0 && phase < MAX_PHASES) { - if (emValue.m[0].phase_angle[phase] != phaseAngle) { - valueChanged = true; - } - emValue.m[0].phase_angle[phase] = phaseAngle; - emValue.measured_values |= EM_VAR_PHASE_ANGLE; - } -} - -void Supla::Sensor::ElectricityMeter::resetReadParameters() { - if (emValue.measured_values != 0) { - emValue.measured_values = 0; - memset(&emValue.m[0], 0, sizeof(TElectricityMeter_Measurement)); - valueChanged = true; - } -} - -// Please implement this class for reading value from elecricity meter device. -// It will be called every 5 s. Use set methods defined above in order to -// set values on channel. Don't use any other method to modify channel values. -void Supla::Sensor::ElectricityMeter::readValuesFromDevice() { -} - -// Put here initialization code for electricity meter device. -// It will be called within SuplaDevce.begin method. -// It should also read first data set, so at the end it should call those two -// methods: -// readValuesFromDevice(); -// updateChannelValues(); -void Supla::Sensor::ElectricityMeter::onInit() { -} - -void Supla::Sensor::ElectricityMeter::iterateAlways() { - if (millis() - lastReadTime > refreshRateSec*1000) { - lastReadTime = millis(); - readValuesFromDevice(); - updateChannelValues(); - } -} - -// Implement this method to reset stored energy value (i.e. to set energy -// counter back to 0 kWh -void Supla::Sensor::ElectricityMeter::resetStorage() { -} - -Supla::Channel *Supla::Sensor::ElectricityMeter::getChannel() { - return &extChannel; -} - -void Supla::Sensor::ElectricityMeter::setRefreshRate(unsigned int sec) { - refreshRateSec = sec; - if (refreshRateSec == 0) { - refreshRateSec = 1; - } -} - -// TODO: move those addAction methods to separate parent -// class i.e. ExtChannelElement - similar to ChannelElement -void Supla::Sensor::ElectricityMeter::addAction(int action, ActionHandler &client, Supla::Condition *condition) { - condition->setClient(client); - condition->setSource(this); - LocalAction::addAction(action, condition, Supla::ON_CHANGE); -} - -void Supla::Sensor::ElectricityMeter::addAction(int action, ActionHandler *client, Supla::Condition *condition) { - addAction(action, *client, condition); -} - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "electricity_meter.h" +#include "../events.h" +#include "../condition.h" + +Supla::Sensor::ElectricityMeter::ElectricityMeter() + : valueChanged(false), lastReadTime(0), refreshRateSec(5) { + extChannel.setType(SUPLA_CHANNELTYPE_ELECTRICITY_METER); + extChannel.setDefault(SUPLA_CHANNELFNC_ELECTRICITY_METER); + memset(&emValue, 0, sizeof(emValue)); + emValue.period = 5; + for (int i = 0; i < MAX_PHASES; i++) { + rawCurrent[i] = 0; + } + currentMeasurementAvailable = false; +} + +void Supla::Sensor::ElectricityMeter::updateChannelValues() { + if (!valueChanged) { + return; + } + valueChanged = false; + + emValue.m_count = 1; + + // Update current messurement precision based on last updates + if (currentMeasurementAvailable) { + bool over65A = false; + for (int i = 0; i < MAX_PHASES; i++) { + if (rawCurrent[i] > 65000) { + over65A = true; + } + } + + for (int i = 0; i < MAX_PHASES; i++) { + if (over65A) { + emValue.m[0].current[i] = rawCurrent[i] / 10; + } else { + emValue.m[0].current[i] = rawCurrent[i]; + } + } + + if (over65A) { + emValue.measured_values &= (!EM_VAR_CURRENT); + emValue.measured_values |= EM_VAR_CURRENT_OVER_65A; + } else { + emValue.measured_values &= (!EM_VAR_CURRENT_OVER_65A); + emValue.measured_values |= EM_VAR_CURRENT; + } + } + + // Prepare extended channel value + srpc_evtool_v2_emextended2extended(&emValue, extChannel.getExtValue()); + extChannel.setNewValue(emValue); + runAction(Supla::ON_CHANGE); +} + +// energy in 0.00001 kWh +void Supla::Sensor::ElectricityMeter::setFwdActEnergy( + int phase, unsigned _supla_int64_t energy) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.total_forward_active_energy[phase] != energy) { + valueChanged = true; + } + emValue.total_forward_active_energy[phase] = energy; + emValue.measured_values |= EM_VAR_FORWARD_ACTIVE_ENERGY; + } +} + +// energy in 0.00001 kWh +void Supla::Sensor::ElectricityMeter::setRvrActEnergy( + int phase, unsigned _supla_int64_t energy) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.total_reverse_active_energy[phase] != energy) { + valueChanged = true; + } + emValue.total_reverse_active_energy[phase] = energy; + emValue.measured_values |= EM_VAR_REVERSE_ACTIVE_ENERGY; + } +} + +// energy in 0.00001 kWh +void Supla::Sensor::ElectricityMeter::setFwdReactEnergy( + int phase, unsigned _supla_int64_t energy) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.total_forward_reactive_energy[phase] != energy) { + valueChanged = true; + } + emValue.total_forward_reactive_energy[phase] = energy; + emValue.measured_values |= EM_VAR_FORWARD_REACTIVE_ENERGY; + } +} + +// energy in 0.00001 kWh +void Supla::Sensor::ElectricityMeter::setRvrReactEnergy( + int phase, unsigned _supla_int64_t energy) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.total_reverse_reactive_energy[phase] != energy) { + valueChanged = true; + } + emValue.total_reverse_reactive_energy[phase] = energy; + emValue.measured_values |= EM_VAR_REVERSE_REACTIVE_ENERGY; + } +} + +// voltage in 0.01 V +void Supla::Sensor::ElectricityMeter::setVoltage( + int phase, unsigned _supla_int16_t voltage) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].voltage[phase] != voltage) { + valueChanged = true; + } + emValue.m[0].voltage[phase] = voltage; + emValue.measured_values |= EM_VAR_VOLTAGE; + } +} + +// current in 0.001 A +void Supla::Sensor::ElectricityMeter::setCurrent( + int phase, unsigned _supla_int_t current) { + if (phase >= 0 && phase < MAX_PHASES) { + if (rawCurrent[phase] != current) { + valueChanged = true; + } + rawCurrent[phase] = current; + currentMeasurementAvailable = true; + } +} + +// Frequency in 0.01 Hz +void Supla::Sensor::ElectricityMeter::setFreq(unsigned _supla_int16_t freq) { + if (emValue.m[0].freq != freq) { + valueChanged = true; + } + emValue.m[0].freq = freq; + emValue.measured_values |= EM_VAR_FREQ; +} + +// power in 0.00001 kW +void Supla::Sensor::ElectricityMeter::setPowerActive(int phase, + _supla_int_t power) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].power_active[phase] != power) { + valueChanged = true; + } + emValue.m[0].power_active[phase] = power; + emValue.measured_values |= EM_VAR_POWER_ACTIVE; + } +} + +// power in 0.00001 kvar +void Supla::Sensor::ElectricityMeter::setPowerReactive(int phase, + _supla_int_t power) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].power_reactive[phase] != power) { + valueChanged = true; + } + emValue.m[0].power_reactive[phase] = power; + emValue.measured_values |= EM_VAR_POWER_REACTIVE; + } +} + +// power in 0.00001 kVA +void Supla::Sensor::ElectricityMeter::setPowerApparent(int phase, + _supla_int_t power) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].power_apparent[phase] != power) { + valueChanged = true; + } + emValue.m[0].power_apparent[phase] = power; + emValue.measured_values |= EM_VAR_POWER_APPARENT; + } +} + +// power in 0.001 +void Supla::Sensor::ElectricityMeter::setPowerFactor(int phase, + _supla_int_t powerFactor) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].power_factor[phase] != powerFactor) { + valueChanged = true; + } + emValue.m[0].power_factor[phase] = powerFactor; + emValue.measured_values |= EM_VAR_POWER_FACTOR; + } +} + +// phase angle in 0.1 degree +void Supla::Sensor::ElectricityMeter::setPhaseAngle(int phase, + _supla_int_t phaseAngle) { + if (phase >= 0 && phase < MAX_PHASES) { + if (emValue.m[0].phase_angle[phase] != phaseAngle) { + valueChanged = true; + } + emValue.m[0].phase_angle[phase] = phaseAngle; + emValue.measured_values |= EM_VAR_PHASE_ANGLE; + } +} + +void Supla::Sensor::ElectricityMeter::resetReadParameters() { + if (emValue.measured_values != 0) { + emValue.measured_values = 0; + memset(&emValue.m[0], 0, sizeof(TElectricityMeter_Measurement)); + valueChanged = true; + } +} + +// Please implement this class for reading value from elecricity meter device. +// It will be called every 5 s. Use set methods defined above in order to +// set values on channel. Don't use any other method to modify channel values. +void Supla::Sensor::ElectricityMeter::readValuesFromDevice() { +} + +// Put here initialization code for electricity meter device. +// It will be called within SuplaDevce.begin method. +// It should also read first data set, so at the end it should call those two +// methods: +// readValuesFromDevice(); +// updateChannelValues(); +void Supla::Sensor::ElectricityMeter::onInit() { +} + +void Supla::Sensor::ElectricityMeter::iterateAlways() { + if (millis() - lastReadTime > refreshRateSec*1000) { + lastReadTime = millis(); + readValuesFromDevice(); + updateChannelValues(); + } +} + +// Implement this method to reset stored energy value (i.e. to set energy +// counter back to 0 kWh +void Supla::Sensor::ElectricityMeter::resetStorage() { +} + +Supla::Channel *Supla::Sensor::ElectricityMeter::getChannel() { + return &extChannel; +} + +void Supla::Sensor::ElectricityMeter::setRefreshRate(unsigned int sec) { + refreshRateSec = sec; + if (refreshRateSec == 0) { + refreshRateSec = 1; + } +} + +// TODO: move those addAction methods to separate parent +// class i.e. ExtChannelElement - similar to ChannelElement +void Supla::Sensor::ElectricityMeter::addAction(int action, ActionHandler &client, Supla::Condition *condition) { + condition->setClient(client); + condition->setSource(this); + LocalAction::addAction(action, condition, Supla::ON_CHANGE); +} + +void Supla::Sensor::ElectricityMeter::addAction(int action, ActionHandler *client, Supla::Condition *condition) { + addAction(action, *client, condition); +} + diff --git a/lib/SuplaDevice/src/supla/sensor/electricity_meter.h b/lib/SuplaDevice/src/supla/sensor/electricity_meter.h index cf48fb47..3361b9f3 100644 --- a/lib/SuplaDevice/src/supla/sensor/electricity_meter.h +++ b/lib/SuplaDevice/src/supla/sensor/electricity_meter.h @@ -1,115 +1,115 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _electricity_meter_h -#define _electricity_meter_h - -#include - -#include "../channel_extended.h" -#include "../element.h" -#include "../local_action.h" -#include - -#define MAX_PHASES 3 - -namespace Supla { -namespace Sensor { -class ElectricityMeter : public Element, public LocalAction { - public: - ElectricityMeter(); - - virtual void updateChannelValues(); - - // energy in 0.00001 kWh - void setFwdActEnergy(int phase, unsigned _supla_int64_t energy); - - // energy in 0.00001 kWh - void setRvrActEnergy(int phase, unsigned _supla_int64_t energy); - - // energy in 0.00001 kWh - void setFwdReactEnergy(int phase, unsigned _supla_int64_t energy); - - // energy in 0.00001 kWh - void setRvrReactEnergy(int phase, unsigned _supla_int64_t energy); - - // voltage in 0.01 V - void setVoltage(int phase, unsigned _supla_int16_t voltage); - - // current in 0.001 A - void setCurrent(int phase, unsigned _supla_int_t current); - - // Frequency in 0.01 Hz - void setFreq(unsigned _supla_int16_t freq); - - // power in 0.00001 kW - void setPowerActive(int phase, _supla_int_t power); - - // power in 0.00001 kvar - void setPowerReactive(int phase, _supla_int_t power); - - // power in 0.00001 kVA - void setPowerApparent(int phase, _supla_int_t power); - - // power in 0.001 - void setPowerFactor(int phase, _supla_int_t powerFactor); - - // phase angle in 0.1 degree - void setPhaseAngle(int phase, _supla_int_t phaseAngle); - - void resetReadParameters(); - - // Please implement this class for reading value from elecricity meter device. - // It will be called every 5 s. Use set methods defined above in order to - // set values on channel. Don't use any other method to modify channel values. - virtual void readValuesFromDevice(); - - // Put here initialization code for electricity meter device. - // It will be called within SuplaDevce.begin method. - // It should also read first data set, so at the end it should call those two - // methods: - // readValuesFromDevice(); - // updateChannelValues(); - void onInit() override; - - void iterateAlways() override; - - // Implement this method to reset stored energy value (i.e. to set energy - // counter back to 0 kWh - virtual void resetStorage(); - - void setRefreshRate(unsigned int sec); - - Channel *getChannel() override; - - virtual void addAction(int action, ActionHandler &client, Supla::Condition *condition); - virtual void addAction(int action, ActionHandler *client, Supla::Condition *condition); - - protected: - TElectricityMeter_ExtendedValue_V2 emValue; - ChannelExtended extChannel; - unsigned _supla_int_t rawCurrent[MAX_PHASES]; - bool valueChanged; - bool currentMeasurementAvailable; - unsigned long lastReadTime; - unsigned int refreshRateSec; -}; - -}; // namespace Sensor -}; // namespace Supla - -#endif - +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _electricity_meter_h +#define _electricity_meter_h + +#include + +#include "../channel_extended.h" +#include "../element.h" +#include "../local_action.h" +#include + +#define MAX_PHASES 3 + +namespace Supla { +namespace Sensor { +class ElectricityMeter : public Element, public LocalAction { + public: + ElectricityMeter(); + + virtual void updateChannelValues(); + + // energy in 0.00001 kWh + void setFwdActEnergy(int phase, unsigned _supla_int64_t energy); + + // energy in 0.00001 kWh + void setRvrActEnergy(int phase, unsigned _supla_int64_t energy); + + // energy in 0.00001 kWh + void setFwdReactEnergy(int phase, unsigned _supla_int64_t energy); + + // energy in 0.00001 kWh + void setRvrReactEnergy(int phase, unsigned _supla_int64_t energy); + + // voltage in 0.01 V + void setVoltage(int phase, unsigned _supla_int16_t voltage); + + // current in 0.001 A + void setCurrent(int phase, unsigned _supla_int_t current); + + // Frequency in 0.01 Hz + void setFreq(unsigned _supla_int16_t freq); + + // power in 0.00001 kW + void setPowerActive(int phase, _supla_int_t power); + + // power in 0.00001 kvar + void setPowerReactive(int phase, _supla_int_t power); + + // power in 0.00001 kVA + void setPowerApparent(int phase, _supla_int_t power); + + // power in 0.001 + void setPowerFactor(int phase, _supla_int_t powerFactor); + + // phase angle in 0.1 degree + void setPhaseAngle(int phase, _supla_int_t phaseAngle); + + void resetReadParameters(); + + // Please implement this class for reading value from elecricity meter device. + // It will be called every 5 s. Use set methods defined above in order to + // set values on channel. Don't use any other method to modify channel values. + virtual void readValuesFromDevice(); + + // Put here initialization code for electricity meter device. + // It will be called within SuplaDevce.begin method. + // It should also read first data set, so at the end it should call those two + // methods: + // readValuesFromDevice(); + // updateChannelValues(); + void onInit() override; + + void iterateAlways() override; + + // Implement this method to reset stored energy value (i.e. to set energy + // counter back to 0 kWh + virtual void resetStorage(); + + void setRefreshRate(unsigned int sec); + + Channel *getChannel() override; + + virtual void addAction(int action, ActionHandler &client, Supla::Condition *condition); + virtual void addAction(int action, ActionHandler *client, Supla::Condition *condition); + + protected: + TElectricityMeter_ExtendedValue_V2 emValue; + ChannelExtended extChannel; + unsigned _supla_int_t rawCurrent[MAX_PHASES]; + bool valueChanged; + bool currentMeasurementAvailable; + unsigned long lastReadTime; + unsigned int refreshRateSec; +}; + +}; // namespace Sensor +}; // namespace Supla + +#endif + diff --git a/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.cpp b/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.cpp index 3b377e47..fea6da86 100644 --- a/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.cpp +++ b/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.cpp @@ -1,81 +1,81 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include - -#include "therm_hygro_press_meter.h" - -Supla::Sensor::ThermHygroPressMeter::ThermHygroPressMeter() { - pressureChannel.setType(SUPLA_CHANNELTYPE_PRESSURESENSOR); - pressureChannel.setDefault(SUPLA_CHANNELFNC_PRESSURESENSOR); -} - -Supla::Sensor::ThermHygroPressMeter::~ThermHygroPressMeter() {} - -double Supla::Sensor::ThermHygroPressMeter::getPressure() { - return PRESSURE_NOT_AVAILABLE; -} - -void Supla::Sensor::ThermHygroPressMeter::iterateAlways() { - if (millis() - lastReadTime > 10000) { - pressureChannel.setNewValue(getPressure()); - } - ThermHygroMeter::iterateAlways(); -} - -bool Supla::Sensor::ThermHygroPressMeter::iterateConnected(void *srpc) { - bool response = true; - if (pressureChannel.isUpdateReady() && - millis() - pressureChannel.lastCommunicationTimeMs > 100) { - pressureChannel.lastCommunicationTimeMs = millis(); - pressureChannel.sendUpdate(srpc); - response = false; - } - - if (!Element::iterateConnected(srpc)) { - response = false; - } - return response; -} - -Supla::Element &Supla::Sensor::ThermHygroPressMeter::disableChannelState() { - pressureChannel.unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); - return ThermHygroMeter::disableChannelState(); -} - -Supla::Channel *Supla::Sensor::ThermHygroPressMeter::getSecondaryChannel() { - return &pressureChannel; -} - -void Supla::Sensor::ThermHygroPressMeter::addAction(int action, - ActionHandler &client, - int event) { - // delegate secondary channel event registration to secondary channel - switch (event) { - case Supla::ON_SECONDARY_CHANNEL_CHANGE: { - getSecondaryChannel()->addAction(action, client, event); - return; - } - } - // delegate all other events to primary channel - channel.addAction(action, client, event); -} - -void Supla::Sensor::ThermHygroPressMeter::addAction(int action, - ActionHandler *client, - int event) { - addAction(action, *client, event); -} +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include "therm_hygro_press_meter.h" + +Supla::Sensor::ThermHygroPressMeter::ThermHygroPressMeter() { + pressureChannel.setType(SUPLA_CHANNELTYPE_PRESSURESENSOR); + pressureChannel.setDefault(SUPLA_CHANNELFNC_PRESSURESENSOR); +} + +Supla::Sensor::ThermHygroPressMeter::~ThermHygroPressMeter() {} + +double Supla::Sensor::ThermHygroPressMeter::getPressure() { + return PRESSURE_NOT_AVAILABLE; +} + +void Supla::Sensor::ThermHygroPressMeter::iterateAlways() { + if (millis() - lastReadTime > 10000) { + pressureChannel.setNewValue(getPressure()); + } + ThermHygroMeter::iterateAlways(); +} + +bool Supla::Sensor::ThermHygroPressMeter::iterateConnected(void *srpc) { + bool response = true; + if (pressureChannel.isUpdateReady() && + millis() - pressureChannel.lastCommunicationTimeMs > 100) { + pressureChannel.lastCommunicationTimeMs = millis(); + pressureChannel.sendUpdate(srpc); + response = false; + } + + if (!Element::iterateConnected(srpc)) { + response = false; + } + return response; +} + +Supla::Element &Supla::Sensor::ThermHygroPressMeter::disableChannelState() { + pressureChannel.unsetFlag(SUPLA_CHANNEL_FLAG_CHANNELSTATE); + return ThermHygroMeter::disableChannelState(); +} + +Supla::Channel *Supla::Sensor::ThermHygroPressMeter::getSecondaryChannel() { + return &pressureChannel; +} + +void Supla::Sensor::ThermHygroPressMeter::addAction(int action, + ActionHandler &client, + int event) { + // delegate secondary channel event registration to secondary channel + switch (event) { + case Supla::ON_SECONDARY_CHANNEL_CHANGE: { + getSecondaryChannel()->addAction(action, client, event); + return; + } + } + // delegate all other events to primary channel + channel.addAction(action, client, event); +} + +void Supla::Sensor::ThermHygroPressMeter::addAction(int action, + ActionHandler *client, + int event) { + addAction(action, *client, event); +} diff --git a/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.h b/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.h index a90c62be..b20b8ce0 100644 --- a/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.h +++ b/lib/SuplaDevice/src/supla/sensor/therm_hygro_press_meter.h @@ -1,48 +1,48 @@ -/* - Copyright (C) AC SOFTWARE SP. Z O.O. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _therm_hygro_press_meter_h -#define _therm_hygro_press_meter_h - -#include "therm_hygro_meter.h" - -#define PRESSURE_NOT_AVAILABLE -1 - -namespace Supla { -namespace Sensor { -class ThermHygroPressMeter : public ThermHygroMeter { - public: - ThermHygroPressMeter(); - virtual ~ThermHygroPressMeter(); - virtual double getPressure(); - void iterateAlways(); - bool iterateConnected(void *srpc); - Element &disableChannelState(); - Channel *getSecondaryChannel(); - - // Override local action methods in order to delegate execution to Channel and - // Secondary Channel - void addAction(int action, ActionHandler &client, int event) override; - void addAction(int action, ActionHandler *client, int event) override; - - protected: - Channel pressureChannel; -}; - -}; // namespace Sensor -}; // namespace Supla - -#endif +/* + Copyright (C) AC SOFTWARE SP. Z O.O. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _therm_hygro_press_meter_h +#define _therm_hygro_press_meter_h + +#include "therm_hygro_meter.h" + +#define PRESSURE_NOT_AVAILABLE -1 + +namespace Supla { +namespace Sensor { +class ThermHygroPressMeter : public ThermHygroMeter { + public: + ThermHygroPressMeter(); + virtual ~ThermHygroPressMeter(); + virtual double getPressure(); + void iterateAlways(); + bool iterateConnected(void *srpc); + Element &disableChannelState(); + Channel *getSecondaryChannel(); + + // Override local action methods in order to delegate execution to Channel and + // Secondary Channel + void addAction(int action, ActionHandler &client, int event) override; + void addAction(int action, ActionHandler *client, int event) override; + + protected: + Channel pressureChannel; +}; + +}; // namespace Sensor +}; // namespace Supla + +#endif diff --git a/platformio.ini b/platformio.ini index 6eaa9bea..1797f12a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,181 +1,181 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[platformio] -default_envs = - GUI_Generic_1MB -; GUI_Generic_1MB-en -; GUI_Generic_2MB -; GUI_Generic_4MB -; GUI_Generic_minimal -; GUI_Generic_lite -; GUI_Generic_sensors -; GUI_Generic_DEBUG -; GUI_Generic_blank -; lib_extra_dirs = ~/Documents/Arduino/libraries - - -[common] -build_flags = - ;-fno-exceptions - ;-Wno-sign-compare - ;-Wno-unused-but-set-variable - ;-Wno-unused-variable - -D ATOMIC_FS_UPDATE - -D BEARSSL_SSL_BASIC - -D BUILD_VERSION='"GUI-Generic 4.3.0"' - ;-D DEFAULT_TEMPLATE_BOARD=19 - -D SUPLA_ENABLE_GUI - ;-D SUPLA_ENABLE_SSL - -D SUPLA_CONFIG - -D SUPLA_OTA - -D SUPLA_MDNS - -D SUPLA_RELAY - -D SUPLA_BUTTON - -D SUPLA_LIMIT_SWITCH - -D SUPLA_ROLLERSHUTTER - -D SUPLA_DS18B20 - -D SUPLA_DHT11 - -D SUPLA_DHT22 - -D SUPLA_SI7021_SONOFF - -D SUPLA_BME280 - -D SUPLA_SHT3x - -D SUPLA_SI7021 - -D SUPLA_MAX6675 - -D SUPLA_HC_SR04 - -D SUPLA_IMPULSE_COUNTER - -D SUPLA_OLED - -D SUPLA_HLW8012 - -D SUPLA_MCP23017 - -D SUPLA_RGBW - -D SUPLA_PUSHOVER - -D SUPLA_DIRECT_LINKS - -D SUPLA_LED - -D SUPLA_NTC_10K - -D SUPLA_PZEM_V_3 - -D SUPLA_BMP280 - -D SUPLA_CSE7766 - -D SUPLA_DEEP_SLEEP - -D SUPLA_MPX_5XXX - -D SUPLA_ANALOG_READING_MAP - -D SUPLA_VL53L0X - -D SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR - -D SUPLA_CONDITIONS - -D SUPLA_RF_BRIDGE - -D SUPLA_HDC1080 - -[env] -lib_deps = - ;milesburton/DallasTemperature@^3.9.1 - ;adafruit/DHT sensor library@^1.4.0 - ;paulstoffregen/OneWire@^2.3.5 - ;adafruit/Adafruit BME280 Library@^2.1.1 - ;closedcube/ClosedCube SHT31D@^1.5.1 - ;adafruit/Adafruit Si7021 Library@^1.3.0 - ;xoseperez/HLW8012 @ ^1.1.1 -extra_scripts = tools/copy_files.py - -[esp82xx_common] -framework = arduino -platform = espressif8266@^3.1.0 -upload_speed = 256000 -monitor_speed = 74880 -upload_resetmethod = nodemcu -board_build.flash_mode = dout -;set frequency to 160MHz -board_build.f_cpu = 160000000L -; set frequency to 80MHz -board_build.f_flash = 80000000L - -[env:GUI_Generic_1MB] -extends = esp82xx_common -board = esp8285 -board_build.ldscript = eagle.flash.1m64.ld -build_flags = ${common.build_flags} - -[env:GUI_Generic_1MB-en] -extends = esp82xx_common -board = esp8285 -board_build.ldscript = eagle.flash.1m64.ld -build_flags = ${common.build_flags} - -D UI_LANGUAGE=en - -[env:GUI_Generic_2MB] -extends = esp82xx_common -board = esp8285 -board_build.ldscript = eagle.flash.2m64.ld -build_flags = ${common.build_flags} - -[env:GUI_Generic_4MB] -extends = esp82xx_common -board = esp12e -board_build.ldscript = eagle.flash.4m1m.ld -build_flags = ${common.build_flags} - -[env:GUI_Generic_minimal] -extends = esp82xx_common -board = esp8285 -board_build.ldscript = eagle.flash.1m64.ld -build_flags = ${common.build_flags} -build_unflags = -D SUPLA_DS18B20 - -D SUPLA_DHT11 - -D SUPLA_DHT22 - -D SUPLA_SI7021_SONOFF - -D SUPLA_BME280 - -D SUPLA_SHT3x - -D SUPLA_SI7021 - -D SUPLA_MAX6675 - -D SUPLA_HC_SR04 - -D SUPLA_IMPULSE_COUNTER - -[env:GUI_Generic_lite] -extends = esp82xx_common -board = esp8285 -board_build.ldscript = eagle.flash.1m64.ld -build_flags = ${common.build_flags} -build_unflags = - -D SUPLA_DHT11 - -D SUPLA_BME280 - -D SUPLA_SHT3x - -D SUPLA_SI7021 - -D SUPLA_MAX6675 - -D SUPLA_HC_SR04 - -D SUPLA_IMPULSE_COUNTER - -[env:GUI_Generic_DEBUG] -extends = esp82xx_common -board = nodemcuv2 -board_build.ldscript = eagle.flash.4m1m.ld -build_flags = ${common.build_flags} - -D DEBUG_MODE - -[env:GUI_Generic_ESP32] -lib_ignore = - ESP8266WiFi - ESP8266Ping - ESP8266WebServer - ESP8266HTTPUpdateServer - ESP8266mDNS - ESPEasy_ESP8266Ping - ESP32 Azure IoT Arduino - ESP32 Async UDP - ESP32 BLE Arduino - SimpleBLE - NetBIOS - ESP32 - Preferences - BluetoothSerial -platform = platformio/espressif32@3.3.2 -framework = arduino -board = esp32dev -monitor_speed = 74880 -board_build.partitions = min_spiffs.csv -build_flags = ${common.build_flags} - ;-D CORE_DEBUG_LEVEL=0 +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = + GUI_Generic_1MB +; GUI_Generic_1MB-en +; GUI_Generic_2MB +; GUI_Generic_4MB +; GUI_Generic_minimal +; GUI_Generic_lite +; GUI_Generic_sensors +; GUI_Generic_DEBUG +; GUI_Generic_blank +; lib_extra_dirs = ~/Documents/Arduino/libraries + + +[common] +build_flags = + ;-fno-exceptions + ;-Wno-sign-compare + ;-Wno-unused-but-set-variable + ;-Wno-unused-variable + -D ATOMIC_FS_UPDATE + -D BEARSSL_SSL_BASIC + -D BUILD_VERSION='"GUI-Generic 4.3.0"' + ;-D DEFAULT_TEMPLATE_BOARD=19 + -D SUPLA_ENABLE_GUI + ;-D SUPLA_ENABLE_SSL + -D SUPLA_CONFIG + -D SUPLA_OTA + -D SUPLA_MDNS + -D SUPLA_RELAY + -D SUPLA_BUTTON + -D SUPLA_LIMIT_SWITCH + -D SUPLA_ROLLERSHUTTER + -D SUPLA_DS18B20 + -D SUPLA_DHT11 + -D SUPLA_DHT22 + -D SUPLA_SI7021_SONOFF + -D SUPLA_BME280 + -D SUPLA_SHT3x + -D SUPLA_SI7021 + -D SUPLA_MAX6675 + -D SUPLA_HC_SR04 + -D SUPLA_IMPULSE_COUNTER + -D SUPLA_OLED + -D SUPLA_HLW8012 + -D SUPLA_MCP23017 + -D SUPLA_RGBW + -D SUPLA_PUSHOVER + -D SUPLA_DIRECT_LINKS + -D SUPLA_LED + -D SUPLA_NTC_10K + -D SUPLA_PZEM_V_3 + -D SUPLA_BMP280 + -D SUPLA_CSE7766 + -D SUPLA_DEEP_SLEEP + -D SUPLA_MPX_5XXX + -D SUPLA_ANALOG_READING_MAP + -D SUPLA_VL53L0X + -D SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR + -D SUPLA_CONDITIONS + -D SUPLA_RF_BRIDGE + -D SUPLA_HDC1080 + +[env] +lib_deps = + ;milesburton/DallasTemperature@^3.9.1 + ;adafruit/DHT sensor library@^1.4.0 + ;paulstoffregen/OneWire@^2.3.5 + ;adafruit/Adafruit BME280 Library@^2.1.1 + ;closedcube/ClosedCube SHT31D@^1.5.1 + ;adafruit/Adafruit Si7021 Library@^1.3.0 + ;xoseperez/HLW8012 @ ^1.1.1 +extra_scripts = tools/copy_files.py + +[esp82xx_common] +framework = arduino +platform = espressif8266@^3.1.0 +upload_speed = 256000 +monitor_speed = 74880 +upload_resetmethod = nodemcu +board_build.flash_mode = dout +;set frequency to 160MHz +board_build.f_cpu = 160000000L +; set frequency to 80MHz +board_build.f_flash = 80000000L + +[env:GUI_Generic_1MB] +extends = esp82xx_common +board = esp8285 +board_build.ldscript = eagle.flash.1m64.ld +build_flags = ${common.build_flags} + +[env:GUI_Generic_1MB-en] +extends = esp82xx_common +board = esp8285 +board_build.ldscript = eagle.flash.1m64.ld +build_flags = ${common.build_flags} + -D UI_LANGUAGE=en + +[env:GUI_Generic_2MB] +extends = esp82xx_common +board = esp8285 +board_build.ldscript = eagle.flash.2m64.ld +build_flags = ${common.build_flags} + +[env:GUI_Generic_4MB] +extends = esp82xx_common +board = esp12e +board_build.ldscript = eagle.flash.4m1m.ld +build_flags = ${common.build_flags} + +[env:GUI_Generic_minimal] +extends = esp82xx_common +board = esp8285 +board_build.ldscript = eagle.flash.1m64.ld +build_flags = ${common.build_flags} +build_unflags = -D SUPLA_DS18B20 + -D SUPLA_DHT11 + -D SUPLA_DHT22 + -D SUPLA_SI7021_SONOFF + -D SUPLA_BME280 + -D SUPLA_SHT3x + -D SUPLA_SI7021 + -D SUPLA_MAX6675 + -D SUPLA_HC_SR04 + -D SUPLA_IMPULSE_COUNTER + +[env:GUI_Generic_lite] +extends = esp82xx_common +board = esp8285 +board_build.ldscript = eagle.flash.1m64.ld +build_flags = ${common.build_flags} +build_unflags = + -D SUPLA_DHT11 + -D SUPLA_BME280 + -D SUPLA_SHT3x + -D SUPLA_SI7021 + -D SUPLA_MAX6675 + -D SUPLA_HC_SR04 + -D SUPLA_IMPULSE_COUNTER + +[env:GUI_Generic_DEBUG] +extends = esp82xx_common +board = nodemcuv2 +board_build.ldscript = eagle.flash.4m1m.ld +build_flags = ${common.build_flags} + -D DEBUG_MODE + +[env:GUI_Generic_ESP32] +lib_ignore = + ESP8266WiFi + ESP8266Ping + ESP8266WebServer + ESP8266HTTPUpdateServer + ESP8266mDNS + ESPEasy_ESP8266Ping + ESP32 Azure IoT Arduino + ESP32 Async UDP + ESP32 BLE Arduino + SimpleBLE + NetBIOS + ESP32 + Preferences + BluetoothSerial +platform = platformio/espressif32@3.3.2 +framework = arduino +board = esp32dev +monitor_speed = 74880 +board_build.partitions = min_spiffs.csv +build_flags = ${common.build_flags} + ;-D CORE_DEBUG_LEVEL=0 diff --git a/src/GUI-Generic.ino b/src/GUI-Generic.ino index f84165e4..38ef0e39 100644 --- a/src/GUI-Generic.ino +++ b/src/GUI-Generic.ino @@ -1,460 +1,460 @@ -/* - Copyright (C) krycha88 - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "SuplaDeviceGUI.h" - -#ifdef SUPLA_PZEM_V_3 -#include -#include -#endif -#ifdef SUPLA_DEEP_SLEEP -#include -#endif - -#ifdef SUPLA_MPX_5XXX -#include -#endif - -#ifdef ARDUINO_ARCH_ESP8266 -extern "C" { -#include "user_interface.h" -} -#endif - -#ifdef SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR -#include -#endif - -void setup() { - uint8_t nr, gpio; - - Serial.begin(74880); - - for (uint8_t t = 4; t > 0; t--) { - Serial.printf("[SETUP] WAIT %d...\n", t); - Serial.flush(); - delay(250); - } - -#ifdef ARDUINO_ARCH_ESP8266 - ESP.wdtDisable(); -#endif - - ConfigManager = new SuplaConfigManager(); - ConfigESP = new SuplaConfigESP(); - -#if defined(SUPLA_RELAY) || defined(SUPLA_ROLLERSHUTTER) - uint8_t rollershutters = ConfigManager->get(KEY_MAX_ROLLERSHUTTER)->getValueInt(); - - for (nr = 0; nr < ConfigManager->get(KEY_MAX_RELAY)->getValueInt(); nr++) { - if (ConfigESP->getGpio(nr, FUNCTION_RELAY) != OFF_GPIO) { - if (rollershutters > 0) { -#ifdef SUPLA_ROLLERSHUTTER - Supla::GUI::addRolleShutter(nr); -#endif - rollershutters--; - nr++; - } - else { -#ifdef SUPLA_RF_BRIDGE - if (ConfigESP->getGpio(FUNCTION_RF_BRIDGE_TRANSMITTER) != OFF_GPIO && - ConfigManager->get(KEY_RF_BRIDGE_TYPE)->getElement(nr).toInt() == Supla::GUI::RFBridgeType::TRANSMITTER && - (strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_ON)->getElement(nr).c_str(), "") != 0 || - strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_OFF)->getElement(nr).c_str(), "") != 0)) { - Supla::GUI::addRelayBridge(nr); - } - else if (ConfigManager->get(KEY_RF_BRIDGE_TYPE)->getElement(nr).toInt() == Supla::GUI::RFBridgeType::RECEIVER && - (strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_ON)->getElement(nr).c_str(), "") != 0 || - strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_OFF)->getElement(nr).c_str(), "") != 0)) { - Supla::GUI::addButtonBridge(nr); - } - else { -#ifdef SUPLA_RELAY - Supla::GUI::addRelay(nr); -#endif - } -#else - -#ifdef SUPLA_RELAY - Supla::GUI::addRelay(nr); -#endif - -#endif - } - -#ifdef SUPLA_PUSHOVER - Supla::GUI::addPushover(nr); -#endif - -#ifdef SUPLA_DIRECT_LINKS - Supla::GUI::addDirectLinks(nr); -#endif - } - } -#endif - -#ifdef SUPLA_LIMIT_SWITCH - for (nr = 0; nr < ConfigManager->get(KEY_MAX_LIMIT_SWITCH)->getValueInt(); nr++) { - if (ConfigESP->getGpio(nr, FUNCTION_LIMIT_SWITCH) != OFF_GPIO) { - new Supla::Sensor::Binary(ConfigESP->getGpio(nr, FUNCTION_LIMIT_SWITCH), true); - } - } -#endif - -#ifdef SUPLA_CONFIG - Supla::GUI::addConfigESP(ConfigESP->getGpio(FUNCTION_CFG_BUTTON), ConfigESP->getGpio(FUNCTION_CFG_LED)); -#endif - -#ifdef SUPLA_DS18B20 - if (ConfigESP->getGpio(FUNCTION_DS18B20) != OFF_GPIO) { - Supla::GUI::addDS18B20MultiThermometer(ConfigESP->getGpio(FUNCTION_DS18B20)); - } -#endif - -#ifdef SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR - for (nr = 0; nr < ConfigManager->get(KEY_MAX_DIRECT_LINKS_SENSOR_THERMOMETR)->getValueInt(); nr++) { - if (strcmp(ConfigManager->get(KEY_DIRECT_LINKS_SENSOR_THERMOMETR)->getElement(nr).c_str(), "") != 0) { - auto directLinkSensorThermometer = new Supla::Sensor::DirectLinksSensorThermometer(ConfigManager->get(KEY_SUPLA_SERVER)->getValue()); - directLinkSensorThermometer->setUrl(ConfigManager->get(KEY_DIRECT_LINKS_SENSOR_THERMOMETR)->getElement(nr).c_str()); - - Supla::GUI::addConditionsTurnON(SENSOR_DIRECT_LINKS_SENSOR_THERMOMETR, directLinkSensorThermometer, nr); - Supla::GUI::addConditionsTurnOFF(SENSOR_DIRECT_LINKS_SENSOR_THERMOMETR, directLinkSensorThermometer, nr); - } - } -#endif - -#ifdef SUPLA_DHT11 - for (nr = 0; nr < ConfigManager->get(KEY_MAX_DHT11)->getValueInt(); nr++) { - if (ConfigESP->getGpio(nr, FUNCTION_DHT11) != OFF_GPIO) { - auto dht11 = new Supla::Sensor::DHT(ConfigESP->getGpio(nr, FUNCTION_DHT11), DHT11); - - Supla::GUI::addConditionsTurnON(SENSOR_DHT11, dht11, nr); - Supla::GUI::addConditionsTurnOFF(SENSOR_DHT11, dht11, nr); - } - } -#endif - -#ifdef SUPLA_DHT22 - for (nr = 0; nr < ConfigManager->get(KEY_MAX_DHT22)->getValueInt(); nr++) { - if (ConfigESP->getGpio(nr, FUNCTION_DHT22) != OFF_GPIO) { - auto dht22 = new Supla::Sensor::DHT(ConfigESP->getGpio(nr, FUNCTION_DHT22), DHT22); - - Supla::GUI::addConditionsTurnON(SENSOR_DHT22, dht22, nr); - Supla::GUI::addConditionsTurnOFF(SENSOR_DHT22, dht22, nr); - } - } -#endif - -#ifdef SUPLA_SI7021_SONOFF - if (ConfigESP->getGpio(FUNCTION_SI7021_SONOFF) != OFF_GPIO) { - auto si7021sonoff = new Supla::Sensor::Si7021Sonoff(ConfigESP->getGpio(FUNCTION_SI7021_SONOFF)); - Supla::GUI::addConditionsTurnON(SENSOR_SI7021_SONOFF, si7021sonoff); - Supla::GUI::addConditionsTurnOFF(SENSOR_SI7021_SONOFF, si7021sonoff); - } -#endif - -#ifdef SUPLA_HC_SR04 - if (ConfigESP->getGpio(FUNCTION_TRIG) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_ECHO) != OFF_GPIO) { - Supla::Sensor::HC_SR04 *hcsr04; - if (ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt() > 0) { - hcsr04 = new Supla::Sensor::HC_SR04_NewPing(ConfigESP->getGpio(FUNCTION_TRIG), ConfigESP->getGpio(FUNCTION_ECHO), 0, - ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt(), - ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt(), 0); - } - else { - hcsr04 = new Supla::Sensor::HC_SR04_NewPing(ConfigESP->getGpio(FUNCTION_TRIG), ConfigESP->getGpio(FUNCTION_ECHO)); - } - - Supla::GUI::addConditionsTurnON(SENSOR_HC_SR04, hcsr04); - Supla::GUI::addConditionsTurnOFF(SENSOR_HC_SR04, hcsr04); - } -#endif - -#ifdef SUPLA_MAX6675 - if (ConfigESP->getGpio(FUNCTION_CLK) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_CS) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_D0) != OFF_GPIO) { - auto thermocouple = - new Supla::Sensor::MAXThermocouple(ConfigESP->getGpio(FUNCTION_CLK), ConfigESP->getGpio(FUNCTION_CS), ConfigESP->getGpio(FUNCTION_D0)); - Supla::GUI::addConditionsTurnON(SENSOR_MAX6675, thermocouple); - Supla::GUI::addConditionsTurnOFF(SENSOR_MAX6675, thermocouple); - } -#endif - -#ifdef SUPLA_NTC_10K - if (ConfigESP->getGpio(FUNCTION_NTC_10K) != OFF_GPIO) { - auto ntc10k = new Supla::Sensor::NTC10K(ConfigESP->getGpio(FUNCTION_NTC_10K)); - Supla::GUI::addConditionsTurnON(SENSOR_NTC_10K, ntc10k); - Supla::GUI::addConditionsTurnOFF(SENSOR_NTC_10K, ntc10k); - } -#endif - -#ifdef SUPLA_MPX_5XXX - if (ConfigESP->getGpio(FUNCTION_MPX_5XXX) != OFF_GPIO) { - Supla::GUI::mpx = new Supla::Sensor::MPX_5XXX(ConfigESP->getGpio(FUNCTION_MPX_5XXX)); - Supla::GUI::addConditionsTurnON(SENSOR_MPX_5XXX, Supla::GUI::mpx); - Supla::GUI::addConditionsTurnOFF(SENSOR_MPX_5XXX, Supla::GUI::mpx); - } -#endif - -#ifdef SUPLA_ANALOG_READING_MAP - if (ConfigESP->getGpio(FUNCTION_ANALOG_READING) != OFF_GPIO) { - Supla::GUI::analog = new Supla::Sensor::AnalogRedingMap(ConfigESP->getGpio(FUNCTION_ANALOG_READING)); - Supla::GUI::addConditionsTurnON(SENSOR_ANALOG_READING_MAP, Supla::GUI::analog); - Supla::GUI::addConditionsTurnOFF(SENSOR_ANALOG_READING_MAP, Supla::GUI::analog); - } -#endif - -#ifdef SUPLA_RGBW - for (nr = 0; nr < ConfigManager->get(KEY_MAX_RGBW)->getValueInt(); nr++) { - Supla::GUI::addRGBWLeds(nr); - } -#endif - -#ifdef SUPLA_IMPULSE_COUNTER - if (ConfigManager->get(KEY_MAX_IMPULSE_COUNTER)->getValueInt() > 0) { - for (nr = 0; nr < ConfigManager->get(KEY_MAX_IMPULSE_COUNTER)->getValueInt(); nr++) { - gpio = ConfigESP->getGpio(nr, FUNCTION_IMPULSE_COUNTER); - if (gpio != OFF_GPIO) { - Supla::GUI::addImpulseCounter(gpio, ConfigESP->getLevel(gpio), ConfigESP->getMemory(gpio), - ConfigManager->get(KEY_IMPULSE_COUNTER_DEBOUNCE_TIMEOUT)->getValueInt()); - } - } - } - -#endif - -#ifdef SUPLA_HLW8012 - if (ConfigESP->getGpio(FUNCTION_CF) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_CF1) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_SEL) != OFF_GPIO) { - Supla::GUI::addHLW8012(ConfigESP->getGpio(FUNCTION_CF), ConfigESP->getGpio(FUNCTION_CF1), ConfigESP->getGpio(FUNCTION_SEL)); - } -#endif - -#ifdef SUPLA_PZEM_V_3 - int8_t pinRX1 = ConfigESP->getGpio(1, FUNCTION_PZEM_RX); - int8_t pinTX1 = ConfigESP->getGpio(1, FUNCTION_PZEM_TX); - int8_t pinRX2 = ConfigESP->getGpio(2, FUNCTION_PZEM_RX); - int8_t pinTX2 = ConfigESP->getGpio(2, FUNCTION_PZEM_TX); - int8_t pinRX3 = ConfigESP->getGpio(3, FUNCTION_PZEM_RX); - int8_t pinTX3 = ConfigESP->getGpio(3, FUNCTION_PZEM_TX); - - if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO && pinRX2 != OFF_GPIO && pinTX2 != OFF_GPIO && pinRX3 != OFF_GPIO && pinTX3 != OFF_GPIO) { -#ifdef ARDUINO_ARCH_ESP32 - new Supla::Sensor::ThreePhasePZEMv3(&Serial, pinRX1, pinTX1, &Serial1, pinRX2, pinTX2, &Serial2, pinRX3, pinTX3); -#else - new Supla::Sensor::ThreePhasePZEMv3(pinRX1, pinTX1, pinRX2, pinTX2, pinRX3, pinTX3); -#endif - } - else if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO && pinTX2 != OFF_GPIO && pinTX3 != OFF_GPIO) { -#ifdef ARDUINO_ARCH_ESP32 - new Supla::Sensor::ThreePhasePZEMv3(&Serial, pinRX1, pinTX1, &Serial1, pinRX1, pinTX2, &Serial2, pinRX1, pinTX3); -#else - new Supla::Sensor::ThreePhasePZEMv3(pinRX1, pinTX1, pinRX1, pinTX2, pinRX1, pinTX3); -#endif - } - else if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO) { -#ifdef ARDUINO_ARCH_ESP32 - new Supla::Sensor::PZEMv3(&Serial, pinRX1, pinTX1); -#else - new Supla::Sensor::PZEMv3(pinRX1, pinTX1); -#endif - } -#endif - -#ifdef SUPLA_CSE7766 - if (ConfigESP->getGpio(FUNCTION_CSE7766_RX) != OFF_GPIO) { - Supla::GUI::addCSE7766(ConfigESP->getGpio(FUNCTION_CSE7766_RX)); - } -#endif - -#ifdef GUI_SENSOR_I2C - if (ConfigESP->getGpio(FUNCTION_SDA) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_SCL) != OFF_GPIO) { - Wire.begin(ConfigESP->getGpio(FUNCTION_SDA), ConfigESP->getGpio(FUNCTION_SCL)); - -#ifdef SUPLA_BME280 - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BME280).toInt()) { - Supla::Sensor::BME280 *bme280; - switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BME280).toInt()) { - case BMx280_ADDRESS_0X76: - bme280 = new Supla::Sensor::BME280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - - Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); - break; - case BMx280_ADDRESS_0X77: - bme280 = new Supla::Sensor::BME280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); - break; - case BMx280_ADDRESS_0X76_AND_0X77: - bme280 = new Supla::Sensor::BME280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - new Supla::Sensor::BME280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - - Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); - break; - } - } -#endif - -#ifdef SUPLA_BMP280 - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BMP280).toInt()) { - Supla::Sensor::BMP280 *bmp280; - switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BMP280).toInt()) { - case BMx280_ADDRESS_0X76: - bmp280 = new Supla::Sensor::BMP280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); - break; - case BMx280_ADDRESS_0X77: - bmp280 = new Supla::Sensor::BMP280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); - break; - case BMx280_ADDRESS_0X76_AND_0X77: - bmp280 = new Supla::Sensor::BMP280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - new Supla::Sensor::BMP280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); - Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); - Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); - break; - } - } -#endif - -#ifdef SUPLA_SHT3x - - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SHT3x).toInt()) { - Supla::Sensor::SHT3x *sht3x; - switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SHT3x).toInt()) { - case SHT3x_ADDRESS_0X44: - sht3x = new Supla::Sensor::SHT3x(0x44); - - Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); - Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); - break; - case SHT3x_ADDRESS_0X45: - sht3x = new Supla::Sensor::SHT3x(0x45); - - Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); - Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); - break; - case SHT3x_ADDRESS_0X44_AND_0X45: - sht3x = new Supla::Sensor::SHT3x(0x44); - new Supla::Sensor::SHT3x(0x45); - - Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); - Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); - break; - } - } -#endif - -#ifdef SUPLA_SI7021 - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SI7021).toInt()) { - auto si7021 = new Supla::Sensor::Si7021(); - Supla::GUI::addConditionsTurnON(SENSOR_SI7021, si7021); - Supla::GUI::addConditionsTurnOFF(SENSOR_SI7021, si7021); - } -#endif - -#ifdef SUPLA_VL53L0X - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_VL53L0X).toInt()) { - auto vl53l0x = new Supla::Sensor::VL_53L0X(); - Supla::GUI::addConditionsTurnON(SENSOR_VL53L0X, vl53l0x); - Supla::GUI::addConditionsTurnOFF(SENSOR_VL53L0X, vl53l0x); - } -#endif - -#ifdef SUPLA_HDC1080 - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_HDC1080).toInt()) { - auto hdc1080 = new Supla::Sensor::HDC1080(); - Supla::GUI::addConditionsTurnON(SENSOR_HDC1080, hdc1080); - Supla::GUI::addConditionsTurnOFF(SENSOR_HDC1080, hdc1080); - } -#endif - -#ifdef SUPLA_OLED - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_OLED).toInt()) { - SuplaOled *oled = new SuplaOled(); - oled->addButtonOled(ConfigESP->getGpio(FUNCTION_CFG_BUTTON)); - } -#endif - -#ifdef SUPLA_MCP23017 - if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_MCP23017).toInt()) { - Supla::Control::MCP_23017 *mcp = new Supla::Control::MCP_23017(); - - for (nr = 0; nr < ConfigManager->get(KEY_MAX_BUTTON)->getValueInt(); nr++) { - gpio = ConfigESP->getGpio(nr, FUNCTION_BUTTON); - if (gpio != OFF_GPIO) - mcp->setPullup(gpio, ConfigESP->getPullUp(gpio), false); - } - -#ifdef ARDUINO_ARCH_ESP8266 - Wire.setClock(400000); -#elif ARDUINO_ARCH_ESP32 - Wire.setClock(100000); -#endif - } -#endif - } -#endif - -#ifdef DEBUG_MODE - new Supla::Sensor::EspFreeHeap(); -#endif - -#ifdef SUPLA_DEEP_SLEEP - if (ConfigManager->get(KEY_DEEP_SLEEP_TIME)->getValueInt() > 0) { - new Supla::Control::DeepSleep(ConfigManager->get(KEY_DEEP_SLEEP_TIME)->getValueInt() * 60, 30); - } -#endif - -#ifdef SUPLA_BUTTON - for (nr = 0; nr < ConfigManager->get(KEY_MAX_BUTTON)->getValueInt(); nr++) { - Supla::GUI::addButton(nr); - } -#endif - - Supla::GUI::begin(); - -#ifdef SUPLA_MPX_5XXX - if (ConfigESP->getGpio(FUNCTION_MPX_5XXX) != OFF_GPIO) { - Supla::Sensor::Percentage *mpxPercent; - - if (Supla::GUI::mpx->getThankHeight() != 0) { - mpxPercent = new Supla::Sensor::Percentage(Supla::GUI::mpx, 0, Supla::GUI::mpx->getThankHeight() * 0.01); - } - else { - mpxPercent = new Supla::Sensor::Percentage(Supla::GUI::mpx, 0, 100); - } - - Supla::GUI::addConditionsTurnON(SENSOR_MPX_5XXX_PERCENT, mpxPercent); - Supla::GUI::addConditionsTurnOFF(SENSOR_MPX_5XXX_PERCENT, mpxPercent); - } -#endif - - Supla::GUI::addCorrectionSensor(); - -#ifdef ARDUINO_ARCH_ESP8266 - // https://github.com/esp8266/Arduino/issues/2070#issuecomment-258660760 - wifi_set_sleep_type(NONE_SLEEP_T); - - ESP.wdtEnable(WDTO_250MS); -#endif -} - -void loop() { - SuplaDevice.iterate(); - delay(25); -} +/* + Copyright (C) krycha88 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "SuplaDeviceGUI.h" + +#ifdef SUPLA_PZEM_V_3 +#include +#include +#endif +#ifdef SUPLA_DEEP_SLEEP +#include +#endif + +#ifdef SUPLA_MPX_5XXX +#include +#endif + +#ifdef ARDUINO_ARCH_ESP8266 +extern "C" { +#include "user_interface.h" +} +#endif + +#ifdef SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR +#include +#endif + +void setup() { + uint8_t nr, gpio; + + Serial.begin(74880); + + for (uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(250); + } + +#ifdef ARDUINO_ARCH_ESP8266 + ESP.wdtDisable(); +#endif + + ConfigManager = new SuplaConfigManager(); + ConfigESP = new SuplaConfigESP(); + +#if defined(SUPLA_RELAY) || defined(SUPLA_ROLLERSHUTTER) + uint8_t rollershutters = ConfigManager->get(KEY_MAX_ROLLERSHUTTER)->getValueInt(); + + for (nr = 0; nr < ConfigManager->get(KEY_MAX_RELAY)->getValueInt(); nr++) { + if (ConfigESP->getGpio(nr, FUNCTION_RELAY) != OFF_GPIO) { + if (rollershutters > 0) { +#ifdef SUPLA_ROLLERSHUTTER + Supla::GUI::addRolleShutter(nr); +#endif + rollershutters--; + nr++; + } + else { +#ifdef SUPLA_RF_BRIDGE + if (ConfigESP->getGpio(FUNCTION_RF_BRIDGE_TRANSMITTER) != OFF_GPIO && + ConfigManager->get(KEY_RF_BRIDGE_TYPE)->getElement(nr).toInt() == Supla::GUI::RFBridgeType::TRANSMITTER && + (strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_ON)->getElement(nr).c_str(), "") != 0 || + strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_OFF)->getElement(nr).c_str(), "") != 0)) { + Supla::GUI::addRelayBridge(nr); + } + else if (ConfigManager->get(KEY_RF_BRIDGE_TYPE)->getElement(nr).toInt() == Supla::GUI::RFBridgeType::RECEIVER && + (strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_ON)->getElement(nr).c_str(), "") != 0 || + strcmp(ConfigManager->get(KEY_RF_BRIDGE_CODE_OFF)->getElement(nr).c_str(), "") != 0)) { + Supla::GUI::addButtonBridge(nr); + } + else { +#ifdef SUPLA_RELAY + Supla::GUI::addRelay(nr); +#endif + } +#else + +#ifdef SUPLA_RELAY + Supla::GUI::addRelay(nr); +#endif + +#endif + } + +#ifdef SUPLA_PUSHOVER + Supla::GUI::addPushover(nr); +#endif + +#ifdef SUPLA_DIRECT_LINKS + Supla::GUI::addDirectLinks(nr); +#endif + } + } +#endif + +#ifdef SUPLA_LIMIT_SWITCH + for (nr = 0; nr < ConfigManager->get(KEY_MAX_LIMIT_SWITCH)->getValueInt(); nr++) { + if (ConfigESP->getGpio(nr, FUNCTION_LIMIT_SWITCH) != OFF_GPIO) { + new Supla::Sensor::Binary(ConfigESP->getGpio(nr, FUNCTION_LIMIT_SWITCH), true); + } + } +#endif + +#ifdef SUPLA_CONFIG + Supla::GUI::addConfigESP(ConfigESP->getGpio(FUNCTION_CFG_BUTTON), ConfigESP->getGpio(FUNCTION_CFG_LED)); +#endif + +#ifdef SUPLA_DS18B20 + if (ConfigESP->getGpio(FUNCTION_DS18B20) != OFF_GPIO) { + Supla::GUI::addDS18B20MultiThermometer(ConfigESP->getGpio(FUNCTION_DS18B20)); + } +#endif + +#ifdef SUPLA_DIRECT_LINKS_SENSOR_THERMOMETR + for (nr = 0; nr < ConfigManager->get(KEY_MAX_DIRECT_LINKS_SENSOR_THERMOMETR)->getValueInt(); nr++) { + if (strcmp(ConfigManager->get(KEY_DIRECT_LINKS_SENSOR_THERMOMETR)->getElement(nr).c_str(), "") != 0) { + auto directLinkSensorThermometer = new Supla::Sensor::DirectLinksSensorThermometer(ConfigManager->get(KEY_SUPLA_SERVER)->getValue()); + directLinkSensorThermometer->setUrl(ConfigManager->get(KEY_DIRECT_LINKS_SENSOR_THERMOMETR)->getElement(nr).c_str()); + + Supla::GUI::addConditionsTurnON(SENSOR_DIRECT_LINKS_SENSOR_THERMOMETR, directLinkSensorThermometer, nr); + Supla::GUI::addConditionsTurnOFF(SENSOR_DIRECT_LINKS_SENSOR_THERMOMETR, directLinkSensorThermometer, nr); + } + } +#endif + +#ifdef SUPLA_DHT11 + for (nr = 0; nr < ConfigManager->get(KEY_MAX_DHT11)->getValueInt(); nr++) { + if (ConfigESP->getGpio(nr, FUNCTION_DHT11) != OFF_GPIO) { + auto dht11 = new Supla::Sensor::DHT(ConfigESP->getGpio(nr, FUNCTION_DHT11), DHT11); + + Supla::GUI::addConditionsTurnON(SENSOR_DHT11, dht11, nr); + Supla::GUI::addConditionsTurnOFF(SENSOR_DHT11, dht11, nr); + } + } +#endif + +#ifdef SUPLA_DHT22 + for (nr = 0; nr < ConfigManager->get(KEY_MAX_DHT22)->getValueInt(); nr++) { + if (ConfigESP->getGpio(nr, FUNCTION_DHT22) != OFF_GPIO) { + auto dht22 = new Supla::Sensor::DHT(ConfigESP->getGpio(nr, FUNCTION_DHT22), DHT22); + + Supla::GUI::addConditionsTurnON(SENSOR_DHT22, dht22, nr); + Supla::GUI::addConditionsTurnOFF(SENSOR_DHT22, dht22, nr); + } + } +#endif + +#ifdef SUPLA_SI7021_SONOFF + if (ConfigESP->getGpio(FUNCTION_SI7021_SONOFF) != OFF_GPIO) { + auto si7021sonoff = new Supla::Sensor::Si7021Sonoff(ConfigESP->getGpio(FUNCTION_SI7021_SONOFF)); + Supla::GUI::addConditionsTurnON(SENSOR_SI7021_SONOFF, si7021sonoff); + Supla::GUI::addConditionsTurnOFF(SENSOR_SI7021_SONOFF, si7021sonoff); + } +#endif + +#ifdef SUPLA_HC_SR04 + if (ConfigESP->getGpio(FUNCTION_TRIG) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_ECHO) != OFF_GPIO) { + Supla::Sensor::HC_SR04 *hcsr04; + if (ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt() > 0) { + hcsr04 = new Supla::Sensor::HC_SR04_NewPing(ConfigESP->getGpio(FUNCTION_TRIG), ConfigESP->getGpio(FUNCTION_ECHO), 0, + ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt(), + ConfigManager->get(KEY_HC_SR04_MAX_SENSOR_READ)->getValueInt(), 0); + } + else { + hcsr04 = new Supla::Sensor::HC_SR04_NewPing(ConfigESP->getGpio(FUNCTION_TRIG), ConfigESP->getGpio(FUNCTION_ECHO)); + } + + Supla::GUI::addConditionsTurnON(SENSOR_HC_SR04, hcsr04); + Supla::GUI::addConditionsTurnOFF(SENSOR_HC_SR04, hcsr04); + } +#endif + +#ifdef SUPLA_MAX6675 + if (ConfigESP->getGpio(FUNCTION_CLK) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_CS) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_D0) != OFF_GPIO) { + auto thermocouple = + new Supla::Sensor::MAXThermocouple(ConfigESP->getGpio(FUNCTION_CLK), ConfigESP->getGpio(FUNCTION_CS), ConfigESP->getGpio(FUNCTION_D0)); + Supla::GUI::addConditionsTurnON(SENSOR_MAX6675, thermocouple); + Supla::GUI::addConditionsTurnOFF(SENSOR_MAX6675, thermocouple); + } +#endif + +#ifdef SUPLA_NTC_10K + if (ConfigESP->getGpio(FUNCTION_NTC_10K) != OFF_GPIO) { + auto ntc10k = new Supla::Sensor::NTC10K(ConfigESP->getGpio(FUNCTION_NTC_10K)); + Supla::GUI::addConditionsTurnON(SENSOR_NTC_10K, ntc10k); + Supla::GUI::addConditionsTurnOFF(SENSOR_NTC_10K, ntc10k); + } +#endif + +#ifdef SUPLA_MPX_5XXX + if (ConfigESP->getGpio(FUNCTION_MPX_5XXX) != OFF_GPIO) { + Supla::GUI::mpx = new Supla::Sensor::MPX_5XXX(ConfigESP->getGpio(FUNCTION_MPX_5XXX)); + Supla::GUI::addConditionsTurnON(SENSOR_MPX_5XXX, Supla::GUI::mpx); + Supla::GUI::addConditionsTurnOFF(SENSOR_MPX_5XXX, Supla::GUI::mpx); + } +#endif + +#ifdef SUPLA_ANALOG_READING_MAP + if (ConfigESP->getGpio(FUNCTION_ANALOG_READING) != OFF_GPIO) { + Supla::GUI::analog = new Supla::Sensor::AnalogRedingMap(ConfigESP->getGpio(FUNCTION_ANALOG_READING)); + Supla::GUI::addConditionsTurnON(SENSOR_ANALOG_READING_MAP, Supla::GUI::analog); + Supla::GUI::addConditionsTurnOFF(SENSOR_ANALOG_READING_MAP, Supla::GUI::analog); + } +#endif + +#ifdef SUPLA_RGBW + for (nr = 0; nr < ConfigManager->get(KEY_MAX_RGBW)->getValueInt(); nr++) { + Supla::GUI::addRGBWLeds(nr); + } +#endif + +#ifdef SUPLA_IMPULSE_COUNTER + if (ConfigManager->get(KEY_MAX_IMPULSE_COUNTER)->getValueInt() > 0) { + for (nr = 0; nr < ConfigManager->get(KEY_MAX_IMPULSE_COUNTER)->getValueInt(); nr++) { + gpio = ConfigESP->getGpio(nr, FUNCTION_IMPULSE_COUNTER); + if (gpio != OFF_GPIO) { + Supla::GUI::addImpulseCounter(gpio, ConfigESP->getLevel(gpio), ConfigESP->getMemory(gpio), + ConfigManager->get(KEY_IMPULSE_COUNTER_DEBOUNCE_TIMEOUT)->getValueInt()); + } + } + } + +#endif + +#ifdef SUPLA_HLW8012 + if (ConfigESP->getGpio(FUNCTION_CF) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_CF1) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_SEL) != OFF_GPIO) { + Supla::GUI::addHLW8012(ConfigESP->getGpio(FUNCTION_CF), ConfigESP->getGpio(FUNCTION_CF1), ConfigESP->getGpio(FUNCTION_SEL)); + } +#endif + +#ifdef SUPLA_PZEM_V_3 + int8_t pinRX1 = ConfigESP->getGpio(1, FUNCTION_PZEM_RX); + int8_t pinTX1 = ConfigESP->getGpio(1, FUNCTION_PZEM_TX); + int8_t pinRX2 = ConfigESP->getGpio(2, FUNCTION_PZEM_RX); + int8_t pinTX2 = ConfigESP->getGpio(2, FUNCTION_PZEM_TX); + int8_t pinRX3 = ConfigESP->getGpio(3, FUNCTION_PZEM_RX); + int8_t pinTX3 = ConfigESP->getGpio(3, FUNCTION_PZEM_TX); + + if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO && pinRX2 != OFF_GPIO && pinTX2 != OFF_GPIO && pinRX3 != OFF_GPIO && pinTX3 != OFF_GPIO) { +#ifdef ARDUINO_ARCH_ESP32 + new Supla::Sensor::ThreePhasePZEMv3(&Serial, pinRX1, pinTX1, &Serial1, pinRX2, pinTX2, &Serial2, pinRX3, pinTX3); +#else + new Supla::Sensor::ThreePhasePZEMv3(pinRX1, pinTX1, pinRX2, pinTX2, pinRX3, pinTX3); +#endif + } + else if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO && pinTX2 != OFF_GPIO && pinTX3 != OFF_GPIO) { +#ifdef ARDUINO_ARCH_ESP32 + new Supla::Sensor::ThreePhasePZEMv3(&Serial, pinRX1, pinTX1, &Serial1, pinRX1, pinTX2, &Serial2, pinRX1, pinTX3); +#else + new Supla::Sensor::ThreePhasePZEMv3(pinRX1, pinTX1, pinRX1, pinTX2, pinRX1, pinTX3); +#endif + } + else if (pinRX1 != OFF_GPIO && pinTX1 != OFF_GPIO) { +#ifdef ARDUINO_ARCH_ESP32 + new Supla::Sensor::PZEMv3(&Serial, pinRX1, pinTX1); +#else + new Supla::Sensor::PZEMv3(pinRX1, pinTX1); +#endif + } +#endif + +#ifdef SUPLA_CSE7766 + if (ConfigESP->getGpio(FUNCTION_CSE7766_RX) != OFF_GPIO) { + Supla::GUI::addCSE7766(ConfigESP->getGpio(FUNCTION_CSE7766_RX)); + } +#endif + +#ifdef GUI_SENSOR_I2C + if (ConfigESP->getGpio(FUNCTION_SDA) != OFF_GPIO && ConfigESP->getGpio(FUNCTION_SCL) != OFF_GPIO) { + Wire.begin(ConfigESP->getGpio(FUNCTION_SDA), ConfigESP->getGpio(FUNCTION_SCL)); + +#ifdef SUPLA_BME280 + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BME280).toInt()) { + Supla::Sensor::BME280 *bme280; + switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BME280).toInt()) { + case BMx280_ADDRESS_0X76: + bme280 = new Supla::Sensor::BME280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + + Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); + break; + case BMx280_ADDRESS_0X77: + bme280 = new Supla::Sensor::BME280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); + break; + case BMx280_ADDRESS_0X76_AND_0X77: + bme280 = new Supla::Sensor::BME280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + new Supla::Sensor::BME280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + + Supla::GUI::addConditionsTurnON(SENSOR_BME280, bme280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BME280, bme280); + break; + } + } +#endif + +#ifdef SUPLA_BMP280 + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BMP280).toInt()) { + Supla::Sensor::BMP280 *bmp280; + switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_BMP280).toInt()) { + case BMx280_ADDRESS_0X76: + bmp280 = new Supla::Sensor::BMP280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); + break; + case BMx280_ADDRESS_0X77: + bmp280 = new Supla::Sensor::BMP280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); + break; + case BMx280_ADDRESS_0X76_AND_0X77: + bmp280 = new Supla::Sensor::BMP280(0x76, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + new Supla::Sensor::BMP280(0x77, ConfigManager->get(KEY_ALTITUDE_BMX280)->getValueInt()); + Supla::GUI::addConditionsTurnON(SENSOR_BMP280, bmp280); + Supla::GUI::addConditionsTurnOFF(SENSOR_BMP280, bmp280); + break; + } + } +#endif + +#ifdef SUPLA_SHT3x + + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SHT3x).toInt()) { + Supla::Sensor::SHT3x *sht3x; + switch (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SHT3x).toInt()) { + case SHT3x_ADDRESS_0X44: + sht3x = new Supla::Sensor::SHT3x(0x44); + + Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); + Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); + break; + case SHT3x_ADDRESS_0X45: + sht3x = new Supla::Sensor::SHT3x(0x45); + + Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); + Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); + break; + case SHT3x_ADDRESS_0X44_AND_0X45: + sht3x = new Supla::Sensor::SHT3x(0x44); + new Supla::Sensor::SHT3x(0x45); + + Supla::GUI::addConditionsTurnON(SENSOR_SHT3x, sht3x); + Supla::GUI::addConditionsTurnOFF(SENSOR_SHT3x, sht3x); + break; + } + } +#endif + +#ifdef SUPLA_SI7021 + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_SI7021).toInt()) { + auto si7021 = new Supla::Sensor::Si7021(); + Supla::GUI::addConditionsTurnON(SENSOR_SI7021, si7021); + Supla::GUI::addConditionsTurnOFF(SENSOR_SI7021, si7021); + } +#endif + +#ifdef SUPLA_VL53L0X + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_VL53L0X).toInt()) { + auto vl53l0x = new Supla::Sensor::VL_53L0X(); + Supla::GUI::addConditionsTurnON(SENSOR_VL53L0X, vl53l0x); + Supla::GUI::addConditionsTurnOFF(SENSOR_VL53L0X, vl53l0x); + } +#endif + +#ifdef SUPLA_HDC1080 + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_HDC1080).toInt()) { + auto hdc1080 = new Supla::Sensor::HDC1080(); + Supla::GUI::addConditionsTurnON(SENSOR_HDC1080, hdc1080); + Supla::GUI::addConditionsTurnOFF(SENSOR_HDC1080, hdc1080); + } +#endif + +#ifdef SUPLA_OLED + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_OLED).toInt()) { + SuplaOled *oled = new SuplaOled(); + oled->addButtonOled(ConfigESP->getGpio(FUNCTION_CFG_BUTTON)); + } +#endif + +#ifdef SUPLA_MCP23017 + if (ConfigManager->get(KEY_ACTIVE_SENSOR)->getElement(SENSOR_I2C_MCP23017).toInt()) { + Supla::Control::MCP_23017 *mcp = new Supla::Control::MCP_23017(); + + for (nr = 0; nr < ConfigManager->get(KEY_MAX_BUTTON)->getValueInt(); nr++) { + gpio = ConfigESP->getGpio(nr, FUNCTION_BUTTON); + if (gpio != OFF_GPIO) + mcp->setPullup(gpio, ConfigESP->getPullUp(gpio), false); + } + +#ifdef ARDUINO_ARCH_ESP8266 + Wire.setClock(400000); +#elif ARDUINO_ARCH_ESP32 + Wire.setClock(100000); +#endif + } +#endif + } +#endif + +#ifdef DEBUG_MODE + new Supla::Sensor::EspFreeHeap(); +#endif + +#ifdef SUPLA_DEEP_SLEEP + if (ConfigManager->get(KEY_DEEP_SLEEP_TIME)->getValueInt() > 0) { + new Supla::Control::DeepSleep(ConfigManager->get(KEY_DEEP_SLEEP_TIME)->getValueInt() * 60, 30); + } +#endif + +#ifdef SUPLA_BUTTON + for (nr = 0; nr < ConfigManager->get(KEY_MAX_BUTTON)->getValueInt(); nr++) { + Supla::GUI::addButton(nr); + } +#endif + + Supla::GUI::begin(); + +#ifdef SUPLA_MPX_5XXX + if (ConfigESP->getGpio(FUNCTION_MPX_5XXX) != OFF_GPIO) { + Supla::Sensor::Percentage *mpxPercent; + + if (Supla::GUI::mpx->getThankHeight() != 0) { + mpxPercent = new Supla::Sensor::Percentage(Supla::GUI::mpx, 0, Supla::GUI::mpx->getThankHeight() * 0.01); + } + else { + mpxPercent = new Supla::Sensor::Percentage(Supla::GUI::mpx, 0, 100); + } + + Supla::GUI::addConditionsTurnON(SENSOR_MPX_5XXX_PERCENT, mpxPercent); + Supla::GUI::addConditionsTurnOFF(SENSOR_MPX_5XXX_PERCENT, mpxPercent); + } +#endif + + Supla::GUI::addCorrectionSensor(); + +#ifdef ARDUINO_ARCH_ESP8266 + // https://github.com/esp8266/Arduino/issues/2070#issuecomment-258660760 + wifi_set_sleep_type(NONE_SLEEP_T); + + ESP.wdtEnable(WDTO_250MS); +#endif +} + +void loop() { + SuplaDevice.iterate(); + delay(25); +} diff --git a/src/Markup.cpp b/src/Markup.cpp index 805aabb4..492c324d 100644 --- a/src/Markup.cpp +++ b/src/Markup.cpp @@ -1,531 +1,531 @@ -/* - Copyright (C) krycha88 - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "Markup.h" -#include "SuplaCommonPROGMEM.h" - -void addForm(String& html, const String& method, const String& action) { - html += "
"; -} - -void addFormEnd(String& html) { - html += "
"; -} - -void addFormHeader(String& html, const String& name) { - html += F("
"); - if (name != "\n") { - html += F("

"); - html += name; - html += F("

"); - } -} - -void addFormHeaderEnd(String& html) { - html += F("
"); -} - -void addBr(String& html) { - html += F("
"); -} - -void addLabel(String& html, const String& name) { - html += F(""); -} - -void addTextBox(String& html, - const String& input_id, - const String& name, - const String& value, - const String& placeholder, - int minlength, - int maxlength, - bool required, - bool readonly, - bool password, - bool underline) { - if (underline) { - html += F(""); - } - else { - html += F(""); - } - - html += F(" "); - WebServer->sendHeader(); -} - -void addTextBox(String& html, - const String& input_id, - const String& name, - uint8_t value_key, - const String& placeholder, - int minlength, - int maxlength, - bool required, - bool readonly, - bool password) { - String value = String(ConfigManager->get(value_key)->getValue()); - return addTextBox(html, input_id, name, value, placeholder, minlength, maxlength, required, readonly, password); -} - -void addTextBox( - String& html, const String& input_id, const String& name, uint8_t value_key, int minlength, int maxlength, bool required, bool readonly) { - return addTextBox(html, input_id, name, value_key, "", minlength, maxlength, required, readonly, false); -} - -void addTextBox( - String& html, const String& input_id, const String& name, const String& value, int minlength, int maxlength, bool required, bool readonly) { - return addTextBox(html, input_id, name, value, "", minlength, maxlength, required, readonly, false); -} - -void addTextBoxPassword(String& html, const String& input_id, const String& name, uint8_t value_key, int minlength, int maxlength, bool required) { - return addTextBox(html, input_id, name, value_key, "", minlength, maxlength, required, false, true); -} - -void addCheckBox(String& html, const String& input_id, const String& name, bool checked) { - html += F(""); -} - -void addNumberBox(String& html, const String& input_id, const String& name, uint8_t value_key, int max) { - html += F("= 0) { - html += F(" max='"); - html += String(max); - html += F("'"); - } - - html += F(" value='"); - html += String(ConfigManager->get(value_key)->getValue()); - html += F("'>"); - WebServer->sendHeader(); -} - -void addNumberBox(String& html, const String& input_id, const String& name, const String& placeholder, bool required, const String& value) { - html += F(""); - WebServer->sendHeader(); -} - -void addLinkBox(String& html, const String& name, const String& url) { - html += F(""); - html += F(""); - html += F(""); - WebServer->sendHeader(); -} - -void addListGPIOLinkBox(String& html, const String& input_id, const String& name, const String& url, uint8_t function) { - addListGPIOBox(html, input_id, name, function, 0, true, url, true); -} - -void addListGPIOLinkBox(String& html, const String& input_id, const String& name, const String& url, uint8_t function, uint8_t nr) { - addListGPIOBox(html, input_id, name, function, nr, true, url); -} - -void addListGPIOBox(String& html, const String& input_id, const String& name, uint8_t function) { - addListGPIOBox(html, input_id, name, function, 0, true, "", true); -} - -void addListGPIOBox( - String& html, const String& input_id, const String& name, uint8_t function, uint8_t nr, bool underline, const String& url, bool no_number) { - uint8_t gpio; - - gpio = ConfigESP->getGpio(nr, function); - - if (underline) { - html += F(""); - } - else { - html += F(""); - } - html += F(""); - - html += F(""); - - html += F(""); -} - -void addGPIOOptionValue(String& html, uint8_t gpio, uint8_t selectedGpio, const String& name) { - html += F("