diff --git a/keywords.txt b/keywords.txt index b9136d0..c3bf3ef 100644 --- a/keywords.txt +++ b/keywords.txt @@ -152,6 +152,7 @@ setModbusStream KEYWORD2 setModbusDEPin KEYWORD2 setModbusDelays KEYWORD2 setModbusFailCounter KEYWORD2 +setModbusLegacyProcess KEYWORD2 setModbusTimeout KEYWORD2 setModbusStreamTimeout KEYWORD2 setModbusInterval KEYWORD2 @@ -224,10 +225,12 @@ ERA_PIN_READ KEYWORD2 ERA_WRITE_DEFAULT KEYWORD2 ERA_PIN_WRITE_DEFAULT KEYWORD2 ERA_PIN_READ_DEFAULT KEYWORD2 +ERA_REPORTABLE_CHANGE_PIN KEYWORD2 ERA_ON_CHANGE KEYWORD2 ERA_ON_RECEIVE KEYWORD2 ERA_ON_CHANGE_DEFAULT KEYWORD2 ERA_ON_RECEIVE_DEFAULT KEYWORD2 +ERA_ON_PUBLISH_PROPERTY KEYWORD2 ERA_CONNECTED KEYWORD2 ERA_DISCONNECTED KEYWORD2 ERA_WAITING KEYWORD2 @@ -238,6 +241,8 @@ ERA_MODBUS_INFO KEYWORD2 ERA_INFO KEYWORD2 ERA_WRITE_CONFIG KEYWORD2 ERA_ATTACH_RUN KEYWORD2 +ERA_DECIMAL_FLOAT KEYWORD2 +ERA_DECIMAL_DOUBLE KEYWORD2 # Special defines ERA_LOG KEYWORD2 @@ -263,6 +268,7 @@ MODBUS_STREAM_TIMEOUT KEYWORD2 ZIGBEE_BAUDRATE KEYWORD2 ZIGBEE_RXD_Pin KEYWORD2 ZIGBEE_TXD_Pin KEYWORD2 +ZIGBEE_DECIMAL_VALUE KEYWORD2 ZIGBEE_STREAM_TIMEOUT KEYWORD2 ZIGBEE_PUBLISH_RETAINED KEYWORD2 diff --git a/library.json b/library.json index e9446bc..e6f4141 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ERa", - "version": "1.4.2", + "version": "1.4.3", "description": "E-Ra by EoH. An IoT Market Enabler! It supports WiFi, Ethernet, Zigbee, Modbus, Serial. Works with boards like Arduino, ESP8266, ESP32, STM32, Raspberry Pi...", "keywords": "ERa, E-Ra, esp8266, esp32, stm32, raspberry-pi, http, mqtt, zigbee, modbus, sensors, control, device, smartphone, mobile, app, web, cloud, communication, protocol, iot, wifi, ethernet, serial", "authors": diff --git a/library.properties b/library.properties index da340e1..5a20b5f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ERa -version=1.4.2 +version=1.4.3 author=EoH Ltd license=MIT maintainer=EoH Ltd diff --git a/linux/MQTT/ERaMqttLinux.hpp b/linux/MQTT/ERaMqttLinux.hpp index f4a36bd..89279b7 100644 --- a/linux/MQTT/ERaMqttLinux.hpp +++ b/linux/MQTT/ERaMqttLinux.hpp @@ -111,6 +111,10 @@ class ERaMqttLinux bool publishState(bool online); bool syncConfig(); + void setConnected(bool enable) { + this->_connected = enable; + } + void setTimeout(uint32_t timeout) { this->mqtt.setTimeout(timeout); } diff --git a/linux/main.py b/linux/main.py index 85ffcda..32fe417 100644 --- a/linux/main.py +++ b/linux/main.py @@ -19,9 +19,9 @@ ERA_MAJOR = 1 ERA_MINOR = 4 -ERA_PATCH = 2 -ERA_VERSION = "1.4.2" -ERA_FIRMWARE_VERSION = "1.4.2" +ERA_PATCH = 3 +ERA_VERSION = "1.4.3" +ERA_FIRMWARE_VERSION = "1.4.3" BUTTON_GPIO = 16 diff --git a/src/ERa/ERaApi.hpp b/src/ERa/ERaApi.hpp index e0fcf4f..6f1e1bc 100644 --- a/src/ERa/ERaApi.hpp +++ b/src/ERa/ERaApi.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ template class ERaApi : public ERaApiHandler + , public ERaComponentHandler #if !defined(ERA_ABBR) , public ERaProperty< ERaApi > #endif @@ -44,6 +46,7 @@ class ERaApi typedef void* TaskHandle_t; typedef ERaApiHandler Handler; + typedef ERaComponentHandler ComponentHandler; protected: #if !defined(ERA_ABBR) @@ -181,7 +184,21 @@ class ERaApi template void configIdWrite(ERaInt_t configId, const T& value, const Args&... tail) { - this->configIdMultiWrite(configId, value, tail...); + this->configIdWriteMulti(configId, value, tail...); + } + + void configIdObject(const char* value) { + ERaDataJson data(value); + this->configIdObject(data); + } + + void configIdObject(cJSON* value) { + ERaDataJson data(value); + this->configIdObject(data); + } + + void configIdObject(ERaDataJson& value) { + this->configIdWriteMultiReal(value, false); } template @@ -319,6 +336,14 @@ class ERaApi } } + bool setVirtualNextRetained(int pin, bool nextRetained) { + return this->ERaPinRp.setVPinNextRetained(pin, nextRetained); + } + + bool getVirtualNextRetained(int pin, bool& retained) { + return this->ERaPinRp.getVPinNextRetained(pin, retained); + } + Flash& getFlash() const { return this->flash; } @@ -347,6 +372,14 @@ class ERaApi this->enableAppLoop = enable; } + void setERaComponent(ERaComponent& _component) override { + ComponentHandler::addComponent(_component); + } + + void setERaComponent(ERaComponent* _pComponent) override { + ComponentHandler::addComponent(_pComponent); + } + void callERaProHandler(const char* deviceId, const cJSON* const root); protected: @@ -365,7 +398,9 @@ class ERaApi void processArduinoPinRequest(const ERaDataBuff& arrayTopic, const char* payload); void processVirtualPinRequest(const ERaDataBuff& arrayTopic, const char* payload); void initPinConfig(); + void parseArduinoPinConfig(cJSON* root); void parsePinConfig(const char* str); + void processPinConfig(cJSON* root, const char* hash, const char* buf); void storePinConfig(const char* str); void removePinConfig(); @@ -395,13 +430,17 @@ class ERaApi this->initERaApiTask(); ERaWatchdogFeed(); + + ComponentHandler::begin(); + + ERaWatchdogFeed(); } - bool run() { + bool run(bool skipTask) { ERA_RUN_YIELD(); if (!this->isTaskRunning()) { - this->handlerAPI(true); + this->handlerAPI(true, skipTask); } ERaWatchdogFeed(); @@ -429,7 +468,7 @@ class ERaApi return this->thisProto().getTransp().run(); } - void handlerAPI(bool feed) { + void handlerAPI(bool feed, bool skipTask) { #if !defined(ERA_ABBR) Property::run(); #endif @@ -440,6 +479,23 @@ class ERaApi } Handler::run(); + + if (feed) { + ERaWatchdogFeed(); + } + + this->thisProto().runEdge(); + + ComponentHandler::run(); + + if (feed) { + ERaWatchdogFeed(); + } + + if (skipTask) { + return; + } + this->runERaApiTask(); } void switchTask() { @@ -454,7 +510,7 @@ class ERaApi void runAPI() { for (;;) { - this->handlerAPI(false); + this->handlerAPI(false, true); ERA_API_YIELD(); if (this->autoSwitchTask && this->connected()) { @@ -668,15 +724,19 @@ class ERaApi } template - void configIdMultiWrite(const Args&... tail) { - ERaRsp_t rsp; + void configIdWriteMulti(const Args&... tail) { ERaDataJson data; data.add_multi(tail...); + this->configIdWriteMultiReal(data, false); + } + + void configIdWriteMultiReal(ERaDataJson& value, bool json = false) { + ERaRsp_t rsp; rsp.type = ERaTypeWriteT::ERA_WRITE_CONFIG_ID_MULTI; - rsp.json = false; + rsp.json = json; rsp.retained = ERA_MQTT_PUBLISH_RETAINED; rsp.id = 0; - rsp.param = data.getObject(); + rsp.param = value.getObject(); this->thisProto().sendCommand(rsp); } @@ -943,6 +1003,18 @@ void ERaApi::initPinConfig() { ptr = nullptr; } +template +inline +void ERaApi::parseArduinoPinConfig(cJSON* root) { + cJSON* item = cJSON_GetObjectItem(root, "arduino_pin"); + if (!cJSON_IsObject(item)) { + return; + } + + this->ERaPinRp.deleteAll(); + this->thisProto().processArduinoPinConfig(item); +} + template inline void ERaApi::parsePinConfig(const char* str) { @@ -957,9 +1029,9 @@ void ERaApi::parsePinConfig(const char* str) { if (cJSON_IsString(item)) { this->ERaPinRp.updateHashID(item->valuestring); } - item = cJSON_GetObjectItem(root, "command"); - if (cJSON_IsString(item)) { - this->thisProto().processDownCommand(str, root, item); + item = cJSON_GetObjectItem(root, "configuration"); + if (cJSON_IsObject(item)) { + this->parseArduinoPinConfig(item); } cJSON_Delete(root); @@ -969,6 +1041,23 @@ void ERaApi::parsePinConfig(const char* str) { ERA_LOG(TAG, ERA_PSTR("Pin configuration loaded from flash")); } +template +inline +void ERaApi::processPinConfig(cJSON* root, const char* hash, const char* buf) { + if (!this->ERaPinRp.updateHashID(hash)) { + this->ERaPinRp.restartAll(); + return; + } + + this->ERaPinRp.deleteAll(); + this->thisProto().processArduinoPinConfig(root); +#if !defined(ERA_ABBR) + Property::updateProperty(this->ERaPinRp); +#endif + this->storePinConfig(buf); + ERaWriteConfig(ERaConfigTypeT::ERA_PIN_CONFIG); +} + template inline void ERaApi::storePinConfig(const char* str) { @@ -1007,6 +1096,7 @@ void ERaApi::removePinConfig() { root = nullptr; return; } + cJSON* data = cJSON_GetObjectItem(root, "data"); cJSON* item = cJSON_GetObjectItem(data, "hash_id"); if (cJSON_IsString(item)) { @@ -1016,6 +1106,7 @@ void ERaApi::removePinConfig() { if (cJSON_IsString(item)) { this->thisProto().Proto::Handler::begin(item->valuestring); } + cJSON_Delete(root); root = nullptr; @@ -1221,7 +1312,7 @@ void ERaApi::appLoop() { if (this->isTaskRunning()) { return; } - this->handlerAPI(true); + this->handlerAPI(true, false); } template diff --git a/src/ERa/ERaCallbacksHelper.hpp b/src/ERa/ERaCallbacksHelper.hpp index 155eeed..46416f4 100644 --- a/src/ERa/ERaCallbacksHelper.hpp +++ b/src/ERa/ERaCallbacksHelper.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,16 @@ class ERaCallbacksHelper ERA_FORCE_UNUSED(pCallbacks); } + virtual void setERaComponent(ERaComponent& _component) { + ERA_LOG_WARNING(TAG, ERA_PSTR("setERaComponent callback default.")); + ERA_FORCE_UNUSED(_component); + } + + virtual void setERaComponent(ERaComponent* _pComponent) { + ERA_LOG_WARNING(TAG, ERA_PSTR("setERaComponent callback default.")); + ERA_FORCE_UNUSED(_pComponent); + } + virtual void setERaTransp(ERaTransp& _transp) { ERA_LOG_WARNING(TAG, ERA_PSTR("setERaTransp callback default.")); ERA_FORCE_UNUSED(_transp); diff --git a/src/ERa/ERaComponent.hpp b/src/ERa/ERaComponent.hpp new file mode 100644 index 0000000..dda6ada --- /dev/null +++ b/src/ERa/ERaComponent.hpp @@ -0,0 +1,36 @@ +#ifndef INC_ERA_COMPONENT_HPP_ +#define INC_ERA_COMPONENT_HPP_ + +#include +#include + +class ERaComponent +{ +public: + ERaComponent() + : next(NULL) + {} + virtual ~ERaComponent() + {} + + virtual void begin() = 0; + virtual void run() = 0; + + ERaComponent* getNext() const { + return this->next; + } + + void setNext(ERaComponent& component) { + this->next = &component; + } + + void setNext(ERaComponent* component) { + this->next = component; + } + +protected: +private: + ERaComponent* next; +}; + +#endif /* INC_ERA_COMPONENT_HPP_ */ diff --git a/src/ERa/ERaComponentHandler.hpp b/src/ERa/ERaComponentHandler.hpp new file mode 100644 index 0000000..0ae5c30 --- /dev/null +++ b/src/ERa/ERaComponentHandler.hpp @@ -0,0 +1,52 @@ +#ifndef INC_ERA_COMPONENT_HANDLER_HPP_ +#define INC_ERA_COMPONENT_HANDLER_HPP_ + +#include + +#define ERA_TEMPLATABLE_COMPONENT_LOOP(method, ...) \ + ERaComponent* component = this->firstComponent; \ + while (component != NULL) { \ + ERaComponent* next = component->getNext(); \ + component->method(__VA_ARGS__); \ + component = next; \ + } + +class ERaComponentHandler +{ +public: + ERaComponentHandler() + : firstComponent(NULL) + , lastComponent(NULL) + {} + ~ERaComponentHandler() + {} + +protected: + void begin() { + ERA_TEMPLATABLE_COMPONENT_LOOP(begin); + } + + void run() { + ERA_TEMPLATABLE_COMPONENT_LOOP(run); + } + + void addComponent(ERaComponent& component) { + this->addComponent(&component); + } + + void addComponent(ERaComponent* pComponent) { + if (this->lastComponent == NULL) { + this->firstComponent = pComponent; + } + else { + this->lastComponent->setNext(pComponent); + } + this->lastComponent = pComponent; + } + +private: + ERaComponent* firstComponent; + ERaComponent* lastComponent; +}; + +#endif /* INC_ERA_COMPONENT_HANDLER_HPP_ */ diff --git a/src/ERa/ERaData.hpp b/src/ERa/ERaData.hpp index 3a7abaf..1e98c28 100644 --- a/src/ERa/ERaData.hpp +++ b/src/ERa/ERaData.hpp @@ -7,6 +7,20 @@ #include #include #include +#include +#include + +#if defined(ERA_DECIMAL_FLOAT) + /* OK, use the specified value */ +#else + #define ERA_DECIMAL_FLOAT 2 +#endif + +#if defined(ERA_DECIMAL_DOUBLE) + /* OK, use the specified value */ +#else + #define ERA_DECIMAL_DOUBLE 6 +#endif using namespace std; @@ -797,7 +811,7 @@ ERaDataBuff::operator char* () const { memset(ptr, 0, this->len); const iterator e = this->end(); for (iterator it = this->begin(); it < e; ++it) { - snprintf(ptr + strlen(ptr), this->len - strlen(ptr), it); + snprintf(ptr + strlen(ptr), this->len - strlen(ptr), "%s", it.getString()); } return ptr; } @@ -1141,12 +1155,12 @@ class ERaDataJson } iterator& operator = (float value) { - cJSON_SetNumberWithDecimal(this->parent, this->item, value, 2); + cJSON_SetNumberWithDecimal(this->parent, this->item, value, ERA_DECIMAL_FLOAT); return (*this); } iterator& operator = (double value) { - cJSON_SetNumberWithDecimal(this->parent, this->item, value, 5); + cJSON_SetNumberWithDecimal(this->parent, this->item, value, ERA_DECIMAL_DOUBLE); return (*this); } @@ -1669,13 +1683,13 @@ void ERaDataJson::set(const char* name, bool value) { inline void ERaDataJson::set(const char* name, float value) { this->create(); - this->setDouble(this->root, name, value, 2); + this->setDouble(this->root, name, value, ERA_DECIMAL_FLOAT); } inline void ERaDataJson::set(const char* name, double value) { this->create(); - this->setDouble(this->root, name, value, 5); + this->setDouble(this->root, name, value, ERA_DECIMAL_DOUBLE); } inline @@ -1706,13 +1720,13 @@ void ERaDataJson::add(const char* name, bool value) { inline void ERaDataJson::add(const char* name, float value) { this->create(); - this->addDouble(this->root, name, value, 2); + this->addDouble(this->root, name, value, ERA_DECIMAL_FLOAT); } inline void ERaDataJson::add(const char* name, double value) { this->create(); - this->addDouble(this->root, name, value, 5); + this->addDouble(this->root, name, value, ERA_DECIMAL_DOUBLE); } inline @@ -1770,13 +1784,13 @@ void ERaDataJson::add(bool value) { inline void ERaDataJson::add(float value) { this->createArray(); - this->addDoubleArray(this->root, value, 2); + this->addDoubleArray(this->root, value, ERA_DECIMAL_FLOAT); } inline void ERaDataJson::add(double value) { this->createArray(); - this->addDoubleArray(this->root, value, 5); + this->addDoubleArray(this->root, value, ERA_DECIMAL_DOUBLE); } inline diff --git a/src/ERa/ERaDebug.hpp b/src/ERa/ERaDebug.hpp index 5ef5929..be57a92 100644 --- a/src/ERa/ERaDebug.hpp +++ b/src/ERa/ERaDebug.hpp @@ -62,6 +62,8 @@ #define ERA_LOG_SECRET(s) ERA_LOG_SECRET_BEGIN s ERA_LOG_SECRET_END + #include + #if defined(ARDUINO) && defined(ESP32) && \ (CORE_DEBUG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) #include @@ -185,7 +187,9 @@ #endif #include + using namespace std; + #define ERA_LOG_TIME() cout << '[' << ERaMillis() << ']' #define ERA_LOG_TAG(tag) cout << '[' << tag << "] " #define ERA_LOG_FN() cout << '[' << ERaFileName(__FILE__) << ':' << __LINE__ << "] " << __FUNCTION__ << "(): " @@ -283,6 +287,14 @@ return rt; \ } +#define ERA_ASSERT_NULL_DEL(data, rt, del) \ + if (data == nullptr) { \ + ERA_ASSERT(data != nullptr); \ + delete del; \ + del = nullptr; \ + return rt; \ + } + #include #include #include diff --git a/src/ERa/ERaModel.hpp b/src/ERa/ERaModel.hpp new file mode 100644 index 0000000..b959add --- /dev/null +++ b/src/ERa/ERaModel.hpp @@ -0,0 +1,51 @@ +#ifndef INC_ERA_MODEL_HPP_ +#define INC_ERA_MODEL_HPP_ + +#include + +class ERaModel +{ +public: + ERaModel() + : pORG(ERA_ORG_NAME) + , pModel(ERA_MODEL_NAME) + {} + ~ERaModel() + {} + + void setVendorName(const char* name) { + this->setERaORG(name); + } + + void setVendorPrefix(const char* prefix) { + this->setERaModel(prefix); + } + + void setERaORG(const char* org) { + if (org == nullptr) { + return; + } + this->pORG = org; + } + + const char* getERaORG() const { + return this->pORG; + } + + void setERaModel(const char* model) { + if (model == nullptr) { + return; + } + this->pModel = model; + } + + const char* getERaModel() const { + return this->pModel; + } + +private: + const char* pORG; + const char* pModel; +}; + +#endif /* INC_ERA_MODEL_HPP_ */ diff --git a/src/ERa/ERaPin.hpp b/src/ERa/ERaPin.hpp index a1d69b6..a93eb85 100644 --- a/src/ERa/ERaPin.hpp +++ b/src/ERa/ERaPin.hpp @@ -68,6 +68,8 @@ class ERaPin private: typedef struct __VPin_t { uint8_t pin; + bool nextRetained; + bool hasNextRetained; VirtualTypeT type; ERaUInt_t configId; } VPin_t; @@ -246,6 +248,7 @@ class ERaPin void enable(Pin_t* pPin); void disable(Pin_t* pPin); void setScale(Pin_t* pPin, float min, float max, float rawMin, float rawMax); + void restartAll(); void enableAll(); void disableAll(); @@ -260,6 +263,9 @@ class ERaPin int findChannelFree() const; bool isVPinExist(uint8_t p, const WrapperBase* param) const; + bool setVPinNextRetained(uint8_t p, bool nextRetained); + bool getVPinNextRetained(uint8_t p, bool& retained) const; + protected: private: Pin_t* setupPinReport(uint8_t p, uint8_t pMode, ERaPin::ReadPinHandler_t readPin, @@ -802,15 +808,21 @@ void ERaPin::setScale(Pin_t* pPin, float min, float max, float rawMin, f } } +template +void ERaPin::restartAll() { + const PinIterator* e = this->pin.end(); + for (PinIterator* it = this->pin.begin(); it != e; it = it->getNext()) { + Pin_t* pPin = it->get(); + this->restartPin(pPin); + } +} + template void ERaPin::enableAll() { const PinIterator* e = this->pin.end(); for (PinIterator* it = this->pin.begin(); it != e; it = it->getNext()) { Pin_t* pPin = it->get(); - if (this->isValidPin(pPin)) { - pPin->enable = true; - pPin->report.enable(); - } + this->enable(pPin); } } @@ -819,10 +831,7 @@ void ERaPin::disableAll() { const PinIterator* e = this->pin.end(); for (PinIterator* it = this->pin.begin(); it != e; it = it->getNext()) { Pin_t* pPin = it->get(); - if (this->isValidPin(pPin)) { - pPin->enable = false; - pPin->report.disable(); - } + this->disable(pPin); } } @@ -1095,6 +1104,45 @@ typename ERaPin::Pin_t* ERaPin::findPinOfChannel(uint8_t channel return nullptr; } +template +bool ERaPin::setVPinNextRetained(uint8_t p, bool nextRetained) { + const VPinIterator* e = this->vPin.end(); + for (VPinIterator* it = this->vPin.begin(); it != e; it = it->getNext()) { + VPin_t* pVPin = it->get(); + if (pVPin == nullptr) { + continue; + } + if (pVPin->pin != p) { + continue; + } + pVPin->hasNextRetained = true; + pVPin->nextRetained = nextRetained; + return true; + } + return false; +} + +template +bool ERaPin::getVPinNextRetained(uint8_t p, bool& retained) const { + const VPinIterator* e = this->vPin.end(); + for (VPinIterator* it = this->vPin.begin(); it != e; it = it->getNext()) { + VPin_t* pVPin = it->get(); + if (pVPin == nullptr) { + continue; + } + if (pVPin->pin != p) { + continue; + } + if (!pVPin->hasNextRetained) { + return false; + } + pVPin->hasNextRetained = false; + retained = pVPin->nextRetained; + return true; + } + return false; +} + using PinEntry = ERaPin::iterator; #endif /* INC_ERA_PIN_HPP_ */ diff --git a/src/ERa/ERaPinDef.hpp b/src/ERa/ERaPinDef.hpp index 528c3da..0166197 100644 --- a/src/ERa/ERaPinDef.hpp +++ b/src/ERa/ERaPinDef.hpp @@ -3,6 +3,12 @@ #include +#if defined(ERA_REPORTABLE_CHANGE_PIN) + /* OK, use the specified value */ +#else + #define ERA_REPORTABLE_CHANGE_PIN 1.0f +#endif + typedef struct __PinConfig_t { uint8_t pin; uint8_t pinMode; @@ -22,7 +28,7 @@ typedef struct __PinConfig_t { : interval(100UL) , minInterval(100UL) , maxInterval(60000UL) - , reportableChange(1.0f) + , reportableChange(ERA_REPORTABLE_CHANGE_PIN) {} __ReportConfig_t(unsigned long _interval, unsigned long _minInterval, unsigned long _maxInterval, float _reportableChange) diff --git a/src/ERa/ERaProperty.hpp b/src/ERa/ERaProperty.hpp index 449c88e..9406790 100644 --- a/src/ERa/ERaProperty.hpp +++ b/src/ERa/ERaProperty.hpp @@ -37,16 +37,21 @@ class ERaProperty typedef std::function PropertyCallback_t; typedef std::function PropertyCallback_p_t; typedef std::function ReportPropertyCallback_t; + typedef std::function OnPublishCallback_t; #else typedef void (*PropertyCallback_t)(void); typedef void (*PropertyCallback_p_t)(void*); typedef void (*ReportPropertyCallback_t)(void*); + typedef bool (*OnPublishCallback_t)(void); #endif const static int MAX_PROPERTIES = ERA_MAX_PROPERTIES; typedef struct __Property_t { ERaProperty::PropertyCallback_t callback; ERaProperty::PropertyCallback_p_t callback_p; +#if defined(ERA_ON_PUBLISH_PROPERTY) + ERaProperty::OnPublishCallback_t onPublishCallback; +#endif ERaReport::iterator report; unsigned long prevMillis; PermissionT permission; @@ -97,9 +102,18 @@ class ERaProperty return (*this); } - iterator& publish() { +#if defined(ERA_ON_PUBLISH_PROPERTY) + iterator& onPublish(ERaProperty::OnPublishCallback_t cb) { + if (this->isValid()) { + this->prop->onPublish(this->pProp, cb); + } + return (*this); + } +#endif + + iterator& publish(bool send = false) { if (this->isValid()) { - this->prop->publish(this->pProp); + this->prop->publish(this->pProp, send); } return (*this); } @@ -445,7 +459,7 @@ class ERaProperty this->addPropertyVirtual(pin, *wrapper, PermissionT::PERMISSION_CLOUD_READ_WRITE). publishOnChange(this->publishSettings.minChange, this->publishSettings.minInterval, this->publishSettings.maxInterval). - publish().allocatorPointer(pValue); + publish(false).allocatorPointer(pValue); } void virtualWriteProperty(uint8_t pin, const ERaParam& value, bool send) { @@ -507,7 +521,7 @@ class ERaProperty this->addPropertyVirtual(pin, *wrapper, PermissionT::PERMISSION_CLOUD_READ_WRITE). publishOnChange(this->publishSettings.minChange, this->publishSettings.minInterval, this->publishSettings.maxInterval). - publish().allocatorPointer(pValue).resetUpdate(); + publish(false).allocatorPointer(pValue).resetUpdate(); } #endif @@ -549,7 +563,7 @@ class ERaProperty this->addPropertyVirtual(pin, *wrapper, PermissionT::PERMISSION_CLOUD_READ_WRITE). publishOnChange(this->publishSettings.minChange, this->publishSettings.minInterval, this->publishSettings.maxInterval). - publish().allocatorPointer(pValue).resetUpdate(); + publish(false).allocatorPointer(pValue).resetUpdate(); } #endif @@ -564,7 +578,10 @@ class ERaProperty void getValue(Property_t* pProp, const ERaParam& param); bool onUpdate(Property_t* pProp, ERaProperty::PropertyCallback_t cb); bool onUpdate(Property_t* pProp, ERaProperty::PropertyCallback_p_t cb, void* args); - bool publish(Property_t* pProp); +#if defined(ERA_ON_PUBLISH_PROPERTY) + bool onPublish(Property_t* pProp, ERaProperty::OnPublishCallback_t cb); +#endif + bool publish(Property_t* pProp, bool send = false); bool publishEvery(Property_t* pProp, unsigned long interval = 1000UL); bool publishOnChange(Property_t* pProp, float minChange = 1.0f, unsigned long minInterval = 1000UL, @@ -581,6 +598,7 @@ class ERaProperty void onCallbackVirtual(const Property_t* const pProp); void onCallbackReal(const Property_t* const pProp); + void onCallbackProperty(const Property_t* const pProp, bool send = false); void onCallback(void* args); #if !defined(ERA_HAS_FUNCTIONAL_H) static void _onCallback(void* args); @@ -899,6 +917,9 @@ typename ERaProperty::Property_t* ERaProperty::setupProperty(uint8_t p pProp->value = value; pProp->callback = nullptr; pProp->callback_p = nullptr; +#if defined(ERA_ON_PUBLISH_PROPERTY) + pProp->onPublishCallback = nullptr; +#endif pProp->param = nullptr; pProp->allocPointer = nullptr; pProp->prevMillis = ERaMillis(); @@ -933,6 +954,9 @@ typename ERaProperty::Property_t* ERaProperty::setupProperty(const cha pProp->value = value; pProp->callback = nullptr; pProp->callback_p = nullptr; +#if defined(ERA_ON_PUBLISH_PROPERTY) + pProp->onPublishCallback = nullptr; +#endif pProp->param = nullptr; pProp->allocPointer = nullptr; pProp->prevMillis = ERaMillis(); @@ -989,13 +1013,28 @@ bool ERaProperty::onUpdate(Property_t* pProp, ERaProperty::PropertyCallback return true; } +#if defined(ERA_ON_PUBLISH_PROPERTY) + template + bool ERaProperty::onPublish(Property_t* pProp, ERaProperty::OnPublishCallback_t cb) { + if (pProp == nullptr) { + return false; + } + if (!this->getFlag(pProp->permission, PermissionT::PERMISSION_READ)) { + return false; + } + + pProp->onPublishCallback = cb; + return true; + } +#endif + template -bool ERaProperty::publish(Property_t* pProp) { +bool ERaProperty::publish(Property_t* pProp, bool send) { if (pProp == nullptr) { return false; } - this->onCallback(pProp); + this->onCallbackProperty(pProp, send); return true; } @@ -1281,14 +1320,26 @@ void ERaProperty::onCallbackReal(const Property_t* const pProp) { } template -void ERaProperty::onCallback(void* args) { - ERaProperty::Property_t* pProp = (ERaProperty::Property_t*)args; +void ERaProperty::onCallbackProperty(const Property_t* const pProp, bool send) { if (pProp == nullptr) { return; } if (pProp->value == nullptr) { return; } + +#if defined(ERA_ON_PUBLISH_PROPERTY) + if (send) { + } + else if (pProp->onPublishCallback == nullptr) { + } + else if (!pProp->onPublishCallback()) { + return; + } +#else + ERA_FORCE_UNUSED(send); +#endif + if (pProp->id.isString()) { this->onCallbackReal(pProp); } @@ -1297,6 +1348,12 @@ void ERaProperty::onCallback(void* args) { } } +template +void ERaProperty::onCallback(void* args) { + ERaProperty::Property_t* pProp = (ERaProperty::Property_t*)args; + this->onCallbackProperty(pProp, false); +} + template bool ERaProperty::isPropertyFree() { if (this->numProperty >= MAX_PROPERTIES) { diff --git a/src/ERa/ERaProtocol.hpp b/src/ERa/ERaProtocol.hpp index a22264c..c7a0dfe 100644 --- a/src/ERa/ERaProtocol.hpp +++ b/src/ERa/ERaProtocol.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ class ERaProto #if defined(ERA_OTA) , public ERaOTA< ERaProto, Flash > #endif + , public ERaModel , public ERaTranspHandler , public ERaServerCallbacks { @@ -75,8 +77,6 @@ class ERaProto , transp(_transp) , pLogger(nullptr) , pServerCallbacks(nullptr) - , pORG(ERA_ORG_NAME) - , pModel(ERA_MODEL_NAME) , _connected(false) , heartbeat(ERA_HEARTBEAT_INTERVAL * 12UL) , lastHeartbeat(0UL) @@ -105,14 +105,9 @@ class ERaProto } void run() { - if (!Base::run() && !this->isConfigMode()) { + if (!Base::run(false) && !this->isConfigMode()) { ERaState::set(StateT::STATE_DISCONNECTED); } - Handler::run(); - if (this->pLogger != nullptr) { - this->pLogger->run(); - } - Base::runERaApiTask(); if (Base::isNeedSyncConfig()) { this->syncConfig(); } @@ -120,36 +115,6 @@ class ERaProto this->publishSelfInfo(); } - void setERaORG(const char* org) { - if (org == nullptr) { - return; - } - this->pORG = org; - } - - const char* getERaORG() const { - return this->pORG; - } - - void setERaModel(const char* model) { - if (model == nullptr) { - return; - } - this->pModel = model; - } - - const char* getERaModel() const { - return this->pModel; - } - - void setVendorName(const char* name) { - this->setERaORG(name); - } - - void setVendorPrefix(const char* prefix) { - this->setERaModel(prefix); - } - void sendCommand(const char* auth, ERaRsp_t& rsp, ApiData_t data = nullptr); void setServerCallbacks(ERaServerCallbacks& callbacks) override { @@ -268,6 +233,14 @@ class ERaProto return true; } + void runEdge() { + Handler::run(); + if (this->pLogger == nullptr) { + return; + } + this->pLogger->run(); + } + virtual void requestListWiFi() override; virtual void responseListWiFi() override; virtual void connectNewWiFi(const char* ssid, const char* pass) override; @@ -290,6 +263,7 @@ class ERaProto void processDownCommand(const char* payload, cJSON* root, cJSON* item); void processFinalize(const char* payload, cJSON* root); void processConfiguration(const char* payload, const char* hash, cJSON* root); + void processArduinoPinConfig(cJSON* root); void processDeviceConfig(cJSON* root, uint8_t type); void processIOPin(cJSON* root); void processPinRequest(const ERaDataBuff& arrayTopic, const char* payload, size_t index); @@ -311,6 +285,7 @@ class ERaProto bool sendPinMultiData(ERaRsp_t& rsp); bool sendConfigIdData(ERaRsp_t& rsp); bool sendConfigIdMultiData(ERaRsp_t& rsp); + bool sendTransport(ERaRsp_t& rsp); #if defined(ERA_MODBUS) bool sendModbusData(ERaRsp_t& rsp); void clearRetainedModbusData(); @@ -372,8 +347,6 @@ class ERaProto Transp& transp; ERaLogger* pLogger; ERaServerCallbacks* pServerCallbacks; - const char* pORG; - const char* pModel; bool _connected; unsigned long heartbeat; @@ -427,6 +400,7 @@ void ERaProto::onDisconnected() { } this->_connected = false; + this->transp.setConnected(false); Base::switchTask(); ERaOnDisconnected(); } @@ -719,28 +693,21 @@ template void ERaProto::processConfiguration(const char* payload, const char* hash, cJSON* root) { cJSON* item = cJSON_GetObjectItem(root, "arduino_pin"); if (cJSON_IsObject(item)) { - Base::getPinRp().deleteAll(); - this->processDeviceConfig(item, ERaChipCfgT::CHIP_IO_PIN); - if (Base::getPinRp().updateHashID(hash)) { -#if !defined(ERA_ABBR) - Base::Property::updateProperty(Base::getPinRp()); -#endif - Base::storePinConfig(payload); - ERaWriteConfig(ERaConfigTypeT::ERA_PIN_CONFIG); - } + Base::processPinConfig(item, hash, payload); } #if defined(ERA_ZIGBEE) item = cJSON_GetObjectItem(root, "zigbee"); if (cJSON_IsObject(item)) { - Base::Zigbee::parseConfigMapDevices(item); - if (Base::Zigbee::updateHashID(hash, true)) { - Base::Zigbee::storeZigbeeConfig(payload); - ERaWriteConfig(ERaConfigTypeT::ERA_ZIGBEE_CONFIG); - } + Base::Zigbee::processConfigMapZigbee(item, hash, payload); } #endif } +template +void ERaProto::processArduinoPinConfig(cJSON* root) { + this->processDeviceConfig(root, ERaChipCfgT::CHIP_IO_PIN); +} + template void ERaProto::processDeviceConfig(cJSON* root, uint8_t type) { cJSON* item = cJSON_GetObjectItem(root, "devices"); @@ -1177,6 +1144,7 @@ bool ERaProto::sendPinData(ERaRsp_t& rsp) { int pMode = Base::getPinRp().findPinMode(rsp.id.getInt()); switch (rsp.type) { case ERaTypeWriteT::ERA_WRITE_VIRTUAL_PIN: { + Base::getVirtualNextRetained(rsp.id.getInt(), rsp.retained); configId = Base::getPinRp().findVPinConfigId(rsp.id.getInt(), rsp.param); if (configId < 0) { break; @@ -1262,7 +1230,7 @@ bool ERaProto::sendPinData(ERaRsp_t& rsp) { return false; } if (rsp.param.isNumber()) { - cJSON_AddNumberWithDecimalToObject(root, name, rsp.param.getDouble(), 5); + cJSON_AddNumberWithDecimalToObject(root, name, rsp.param.getDouble(), ERA_DECIMAL_DOUBLE); } else if (rsp.param.isString()) { cJSON_AddStringToObject(root, name, rsp.param.getString()); @@ -1303,7 +1271,7 @@ bool ERaProto::sendConfigIdData(ERaRsp_t& rsp) { return false; } if (rsp.param.isNumber()) { - cJSON_AddNumberWithDecimalToObject(root, "v", rsp.param.getDouble(), 5); + cJSON_AddNumberWithDecimalToObject(root, "v", rsp.param.getDouble(), ERA_DECIMAL_DOUBLE); } else if (rsp.param.isString()) { cJSON_AddStringToObject(root, "v", rsp.param.getString()); @@ -1332,6 +1300,34 @@ bool ERaProto::sendConfigIdMultiData(ERaRsp_t& rsp) { rsp.param, rsp.retained); } +template +bool ERaProto::sendTransport(ERaRsp_t& rsp) { + switch (rsp.type) { + case ERaTypeWriteT::ERA_WRITE_VIRTUAL_PIN: { + ERaInt_t configId = Base::getPinRp().findVPinConfigId(rsp.id.getInt(), rsp.param); + if (configId < 0) { + return false; + } + rsp.id = configId; + } + break; + case ERaTypeWriteT::ERA_WRITE_PIN: { + ERaInt_t configId = Base::getPinRp().findConfigId(rsp.id.getInt(), rsp.param); + if (configId < 0) { + return false; + } + rsp.id = configId; + } + break; + case ERaTypeWriteT::ERA_WRITE_CONFIG_ID: + break; + default: + return false; + } + + return this->sendConfigIdData(rsp); +} + #if defined(ERA_MODBUS) template bool ERaProto::sendModbusData(ERaRsp_t& rsp) { @@ -1456,7 +1452,7 @@ void ERaProto::sendCommand(const char* auth, ERaRsp_t& rsp, ApiDa return; } if (rsp.param.isNumber()) { - cJSON_AddNumberWithDecimalToObject(root, "value", rsp.param.getDouble(), 5); + cJSON_AddNumberWithDecimalToObject(root, "value", rsp.param.getDouble(), ERA_DECIMAL_DOUBLE); } else if (rsp.param.isString()) { cJSON_AddStringToObject(root, "value", rsp.param.getString()); @@ -1529,6 +1525,7 @@ void ERaProto::sendCommandVirtualMulti(const char* auth, ERaRsp_t template void ERaProto::sendCommand(ERaRsp_t& rsp, ApiData_t data) { if (!this->connected()) { + this->sendTransport(rsp); return; } diff --git a/src/ERa/ERaReport.cpp b/src/ERa/ERaReport.cpp index c04c74a..73db1e3 100644 --- a/src/ERa/ERaReport.cpp +++ b/src/ERa/ERaReport.cpp @@ -434,13 +434,19 @@ void ERaReport::setScale(Report_t* pReport, float min, float max, float rawMin, */ } +void ERaReport::restartAll() { + const ReportIterator* e = this->report.end(); + for (ReportIterator* it = this->report.begin(); it != e; it = it->getNext()) { + Report_t* pReport = it->get(); + this->restartReport(pReport); + } +} + void ERaReport::enableAll() { const ReportIterator* e = this->report.end(); for (ReportIterator* it = this->report.begin(); it != e; it = it->getNext()) { Report_t* pReport = it->get(); - if (this->isValidReport(pReport)) { - pReport->enable = true; - } + this->enable(pReport); } } @@ -448,9 +454,7 @@ void ERaReport::disableAll() { const ReportIterator* e = this->report.end(); for (ReportIterator* it = this->report.begin(); it != e; it = it->getNext()) { Report_t* pReport = it->get(); - if (this->isValidReport(pReport)) { - pReport->enable = false; - } + this->disable(pReport); } } diff --git a/src/ERa/ERaReport.hpp b/src/ERa/ERaReport.hpp index 8de6b72..1ce7424 100644 --- a/src/ERa/ERaReport.hpp +++ b/src/ERa/ERaReport.hpp @@ -350,6 +350,7 @@ class ERaReport void enable(Report_t* pReport); void disable(Report_t* pReport); void setScale(Report_t* pReport, float min, float max, float rawMin, float rawMax); + void restartAll(); void enableAll(); void disableAll(); diff --git a/src/ERa/ERaTimeLib.hpp b/src/ERa/ERaTimeLib.hpp index b50c0d7..2b3df95 100644 --- a/src/ERa/ERaTimeLib.hpp +++ b/src/ERa/ERaTimeLib.hpp @@ -58,6 +58,9 @@ class ERaTime virtual void begin() = 0; virtual void run() = 0; + virtual void setTimeZone(long) { + } + virtual long getTimeZone() { return 0L; } diff --git a/src/ERa/ERaTopic.hpp b/src/ERa/ERaTopic.hpp index e2e7ef7..88db0a9 100644 --- a/src/ERa/ERaTopic.hpp +++ b/src/ERa/ERaTopic.hpp @@ -51,9 +51,6 @@ Topic format: #define ERA_PUB_PREFIX_ARDUINO_DOWN_TOPIC "/arduino_pin/" ERA_INTEGER_C_TYPE #define ERA_PUB_PREFIX_VIRTUAL_DOWN_TOPIC "/virtual_pin/" ERA_INTEGER_C_TYPE -#if defined(ERA_ZIGBEE) || \ - defined(ERA_SPECIFIC) - #define ERA_PUB_PREFIX_ZIGBEE_DOWN_TOPIC "/zigbee/%s/down" -#endif +#define ERA_PUB_PREFIX_ZIGBEE_DOWN_TOPIC "/zigbee/%s/down" #endif /* INC_ERA_TOPIC_HPP_ */ diff --git a/src/ERa/ERaVersion.hpp b/src/ERa/ERaVersion.hpp index 9f02118..a7488db 100644 --- a/src/ERa/ERaVersion.hpp +++ b/src/ERa/ERaVersion.hpp @@ -3,7 +3,7 @@ #define ERA_MAJOR 1 #define ERA_MINOR 4 -#define ERA_PATCH 2 +#define ERA_PATCH 3 #define ERA_VERSION_TO_STR_2(val) # val #define ERA_VERSION_TO_STR(val) ERA_VERSION_TO_STR_2(val) @@ -17,7 +17,7 @@ #define ERA_VERSION ERA_VERSION_TO_STR(ERA_MAJOR) "." \ ERA_VERSION_TO_STR(ERA_MINOR) "." \ ERA_VERSION_TO_STR(ERA_PATCH) -#define ERA_VERSION_1_4_2 +#define ERA_VERSION_1_4_3 #if !defined(ERA_FIRMWARE_VERSION) #define ERA_FIRMWARE_VERSION ERA_VERSION diff --git a/src/ERa/types/WrapperString.hpp b/src/ERa/types/WrapperString.hpp index 5058cd9..6d123d7 100644 --- a/src/ERa/types/WrapperString.hpp +++ b/src/ERa/types/WrapperString.hpp @@ -533,7 +533,7 @@ class WrapperString; this->value.buffer = copy; this->value.capacity = (newLen + 1); } - snprintf(this->value.buffer + oldLen, newLen - oldLen + 1, cstr); + snprintf(this->value.buffer + oldLen, newLen - oldLen + 1, "%s", cstr); this->value.buffer[newLen] = '\0'; this->value.length = newLen; this->isUpdated = true; @@ -1607,12 +1607,12 @@ class WrapperString; if (copy == nullptr) { return; } - snprintf(copy, len + 1, cstr); + snprintf(copy, len + 1, "%s", cstr); this->value.buffer = copy; this->value.capacity = (len + 1); } else { - snprintf(this->value.buffer, this->value.capacity, cstr); + snprintf(this->value.buffer, this->value.capacity, "%s", cstr); } this->value.buffer[len] = '\0'; this->value.length = len; diff --git a/src/MQTT/ERaMqtt.hpp b/src/MQTT/ERaMqtt.hpp index d7cc5d4..87fa363 100644 --- a/src/MQTT/ERaMqtt.hpp +++ b/src/MQTT/ERaMqtt.hpp @@ -145,6 +145,10 @@ class ERaMqtt bool publishState(bool online); bool syncConfig(); + void setConnected(bool enable) { + this->_connected = enable; + } + void setTimeout(uint32_t timeout) { this->mqtt.setTimeout(timeout); } diff --git a/src/Modbus/ERaModbus.hpp b/src/Modbus/ERaModbus.hpp index 61c31fd..8e8f9f5 100644 --- a/src/Modbus/ERaModbus.hpp +++ b/src/Modbus/ERaModbus.hpp @@ -84,6 +84,8 @@ class ERaModbus , wifiConfig(false) , actionWriteTask(true) , runApiResponse(true) + , legacyProcess(false) + , currentParam(NULL) {} ~ERaModbus() { @@ -142,6 +144,10 @@ class ERaModbus this->failCounter.start = start; } + void setModbusLegacyProcess(bool enable) { + this->legacyProcess = enable; + } + void setSkipModbus(bool skip) { this->skipModbus = skip; } @@ -187,17 +193,8 @@ class ERaModbus this->waitTCPIpReady(!forever); for (;;) { this->processModbusScan(); - this->resizeConfig(); - if (!ERaRemainingTime(this->modbusConfig->modbusInterval.prevMillis, this->modbusConfig->modbusInterval.delay)) { - this->modbusConfig->modbusInterval.prevMillis = ERaMillis(); - this->readModbusConfig(); - this->getModbusAction(false); - this->getModbusActionRaw(false); - ModbusStream::streamStart(); - } - else { - this->waitRequest(); - } + this->updateConfig(); + this->handlerModbusRead(); #if !defined(ERA_NO_RTOS) this->timer.run(); #endif @@ -224,49 +221,72 @@ class ERaModbus } } + void handlerModbusRead() { + this->readModbusConfig(); + this->getModbusAction(false); + this->getModbusActionRaw(false); + } + void parseModbusConfig(const void* config, const char* hash, const char* buf, bool isControl = false, bool json = false) { ModbusState::set(ModbusStateT::STATE_MB_PARSE); if (isControl) { - ERaGuardLock(this->mutex); - this->modbusControl->parseConfig(config, json); - if (this->modbusControl->updateHashID(hash)) { - this->thisApi().writeToFlash(FILENAME_CONTROL, buf); - ERA_LOG(TAG, ERA_PSTR("Modbus control stored to flash")); - ERaWriteConfig(ERaConfigTypeT::ERA_MODBUS_CONTROL); -#if !defined(ERA_PNP_MODBUS) - this->modbusControl->updated(); -#endif - } - ModbusState::set(ModbusStateT::STATE_MB_PARSE); - ERaGuardUnlock(this->mutex); - this->initModbus(); + this->processModbusControl(config, hash, buf, json); } else { - ERaGuardLock(this->mutex); + this->processModbusConfig(config, hash, buf, json); + } + } + + void processModbusConfig(const void* config, const char* hash, + const char* buf, bool json = false) { + ERaGuardLock(this->mutex); + if (this->modbusConfig->updateHashID(hash)) { this->modbusConfig->parseConfig(config, json); ModbusTransp::parseConfig(config, json); - if (this->modbusConfig->updateHashID(hash)) { - this->clearDataBuff(); - this->thisApi().writeToFlash(FILENAME_CONFIG, buf); - ERA_LOG(TAG, ERA_PSTR("Modbus configuration stored to flash")); - if (this->wifiConfig && this->modbusConfig->isWiFi) { - this->thisApi().connectNewWiFi(this->modbusConfig->ssid, - this->modbusConfig->pass); - } - ERaWriteConfig(ERaConfigTypeT::ERA_MODBUS_CONFIG); - this->modbusConfig->updated(); - } - ModbusState::set(ModbusStateT::STATE_MB_PARSE); - ERaGuardUnlock(this->mutex); - this->initModbus(); - if (this->initialized) { - ModbusStream::setBaudRate(this->modbusConfig->baudSpeed); + this->clearDataBuff(); + this->thisApi().writeToFlash(FILENAME_CONFIG, buf); + ERA_LOG(TAG, ERA_PSTR("Modbus configuration stored to flash")); + if (this->wifiConfig && this->modbusConfig->isWiFi) { + this->thisApi().connectNewWiFi(this->modbusConfig->ssid, + this->modbusConfig->pass); } - this->executeNow(); + ERaWriteConfig(ERaConfigTypeT::ERA_MODBUS_CONFIG); + this->modbusConfig->updated(); + } + else if (hash == nullptr) { + this->modbusConfig->parseConfig(config, json); + ModbusTransp::parseConfig(config, json); + this->clearDataBuff(); + } + ModbusState::set(ModbusStateT::STATE_MB_PARSE); + ERaGuardUnlock(this->mutex); + this->initModbus(); + if (this->initialized) { + ModbusStream::setBaudRate(this->modbusConfig->baudSpeed); } } + void processModbusControl(const void* config, const char* hash, + const char* buf, bool json = false) { + ERaGuardLock(this->mutex); + if (this->modbusControl->updateHashID(hash)) { + this->modbusControl->parseConfig(config, json); + this->thisApi().writeToFlash(FILENAME_CONTROL, buf); + ERA_LOG(TAG, ERA_PSTR("Modbus control stored to flash")); + ERaWriteConfig(ERaConfigTypeT::ERA_MODBUS_CONTROL); +#if !defined(ERA_PNP_MODBUS) + this->modbusControl->updated(); +#endif + } + else if (hash == nullptr) { + this->modbusControl->parseConfig(config, json); + } + ModbusState::set(ModbusStateT::STATE_MB_PARSE); + ERaGuardUnlock(this->mutex); + this->initModbus(); + } + void parseModbusScan(const char* config) { this->modbusScan->getInstance(); this->modbusScan->parseConfig(config); @@ -387,7 +407,12 @@ class ERaModbus } cJSON* data = cJSON_GetObjectItem(root, "data"); - cJSON* item = cJSON_GetObjectItem(data, name); + cJSON* item = cJSON_GetObjectItem(data, "hash_id"); + if (cJSON_IsString(item)) { + config->updateHashID(item->valuestring, true); + } + + item = cJSON_GetObjectItem(data, name); if (item == nullptr) { item = cJSON_GetObjectItem(data, jsName); } @@ -402,11 +427,6 @@ class ERaModbus } } - item = cJSON_GetObjectItem(data, "hash_id"); - if (cJSON_IsString(item)) { - config->updateHashID(item->valuestring, true); - } - cJSON_Delete(root); root = nullptr; data = nullptr; @@ -417,7 +437,7 @@ class ERaModbus this->initModbus(); } - void resizeConfig() { + void updateConfig() { if (ModbusState::is(ModbusStateT::STATE_MB_PARSE)) { this->modbusConfig->resize(); this->modbusControl->resize(); @@ -431,6 +451,10 @@ class ERaModbus ModbusTransp::clearConfigId(); } } + if (this->isStateUpdate()) { + this->resetCurrentParam(); + this->executeNow(); + } ModbusState::set(ModbusStateT::STATE_MB_RUNNING); } @@ -503,7 +527,6 @@ class ERaModbus } this->actionModbus(req); if (ModbusAction::isEmptyRequest()) { - this->executeNow(); if (!ModbusState::is(ModbusStateT::STATE_MB_PARSE)) { ModbusState::set(ModbusStateT::STATE_MB_CONTROLLED); } @@ -525,7 +548,6 @@ class ERaModbus ModbusActionRaw_t& req = ModbusAction::getRawRequest(); this->actionModbusRaw(req); if (ModbusAction::isEmptyRawRequest()) { - this->executeNow(); if (!ModbusState::is(ModbusStateT::STATE_MB_PARSE)) { ModbusState::set(ModbusStateT::STATE_MB_CONTROLLED); } @@ -536,6 +558,7 @@ class ERaModbus } } + void publishModbusData(); void readModbusConfig(); bool checkPubDataInterval(); void delayModbus(ERaUInt_t address, bool unlock = false, bool skip = false); @@ -571,17 +594,22 @@ class ERaModbus void switchToTransmit(); void switchToReceive(); - bool isRTU() { + bool isRTU() const { return (this->transp == ModbusTransportT::MODBUS_TRANSPORT_RTU); } - bool isEmptyConfig() { + bool isEmptyConfig() const { return (this->modbusConfig->modbusConfigParam.isEmpty() && this->modbusControl->modbusConfigParam.isEmpty()); } + bool isStateUpdate() const { + return (ModbusState::is(ModbusStateT::STATE_MB_PARSE) || + ModbusState::is(ModbusStateT::STATE_MB_CONTROLLED)); + } + #if !defined(ERA_NO_RTOS) - bool isTaskRunning() { + bool isTaskRunning() const { return ((this->_modbusTask != NULL) && (this->_writeModbusTask != NULL)); } @@ -626,7 +654,20 @@ class ERaModbus } void executeNow() { - this->modbusConfig->modbusInterval.prevMillis = (ERaMillis() - this->modbusConfig->modbusInterval.delay + ERA_MODBUS_EXECUTE_MS); + this->modbusConfig->modbusInterval.prevMillis = ( + ERaMillis() - this->modbusConfig->modbusInterval.delay + ERA_MODBUS_EXECUTE_MS + ); + } + + void nextCurrentParam() { + if (!ModbusTransp::canNextRequest()) { + return; + } + this->currentParam = this->currentParam->getNext(); + } + + void resetCurrentParam() { + this->currentParam = nullptr; } inline @@ -683,21 +724,13 @@ class ERaModbus bool wifiConfig; bool actionWriteTask; volatile bool runApiResponse; + + bool legacyProcess; + ERaList::iterator* currentParam; }; template -void ERaModbus::readModbusConfig() { - if (this->modbusConfig->modbusConfigParam.isEmpty()) { - return; - } - this->dataBuff.clear(); - const ERaList::iterator* e = this->modbusConfig->modbusConfigParam.end(); - for (ERaList::iterator* it = this->modbusConfig->modbusConfigParam.begin(); it != e; it = it->getNext()) { - ModbusConfig_t* param = it->get(); - if (!this->handlerModbusRead(param)) { - return; - } - } +void ERaModbus::publishModbusData() { if (this->dataBuff.isEmpty()) { return; } @@ -710,9 +743,9 @@ void ERaModbus::readModbusConfig() { } #endif this->dataBuff.add_multi(ERA_F(MODBUS_STRING_FAIL_READ), this->failRead, - ERA_F(MODBUS_STRING_FAIL_WRITE), this->failWrite, - ERA_F(MODBUS_STRING_TOTAL_READ), this->totalRead, - ERA_F(MODBUS_STRING_TOTAL_WRITE), this->totalWrite); + ERA_F(MODBUS_STRING_FAIL_WRITE), this->failWrite, + ERA_F(MODBUS_STRING_TOTAL_READ), this->totalRead, + ERA_F(MODBUS_STRING_TOTAL_WRITE), this->totalWrite); this->addScanData(); this->dataBuff.done(); @@ -722,6 +755,35 @@ void ERaModbus::readModbusConfig() { this->thisApi().modbusDataWrite(&this->dataBuff); } +template +void ERaModbus::readModbusConfig() { + if (this->modbusConfig->modbusConfigParam.isEmpty()) { + return this->waitRequest(); + } + + if (this->currentParam != nullptr) { + this->nextCurrentParam(); + } + else if (ERaRemainingTime(this->modbusConfig->modbusInterval.prevMillis, + this->modbusConfig->modbusInterval.delay)) { + return this->waitRequest(); + } + else { + this->dataBuff.clear(); + this->modbusConfig->modbusInterval.prevMillis = ERaMillis(); + this->currentParam = this->modbusConfig->modbusConfigParam.begin(); + ModbusTransp::reset(); + ModbusStream::streamStart(); + } + + if (this->currentParam == nullptr) { + return this->publishModbusData(); + } + + ModbusConfig_t* param = this->currentParam->get(); + this->handlerModbusRead(param); +} + template bool ERaModbus::checkPubDataInterval() { unsigned long currentMillis = ERaMillis(); @@ -787,12 +849,11 @@ void ERaModbus::delays(MillisTime_t ms) { do { #if defined(ERA_NO_RTOS) if (this->runApiResponse) { - this->thisApi().run(); + this->thisApi().run(true); this->thisApi().runZigbee(); } #endif - if (ModbusState::is(ModbusStateT::STATE_MB_PARSE) || - ModbusState::is(ModbusStateT::STATE_MB_CONTROLLED)) { + if (this->isStateUpdate()) { break; } this->waitRequest(); @@ -881,13 +942,16 @@ void ERaModbus::processModbusScan() { param.addr = i; ERaGuardLock(this->mutex); this->nextTransport(param); - if (ModbusTransp::readHoldingRegisters(this->transp, param, true)) { + if (ModbusTransp::readHoldingRegistersLegacy(this->transp, param, true)) { this->modbusScan->addr[this->modbusScan->numberDevice++] = i; } this->delays(100); ERaGuardUnlock(this->mutex); ERA_MODBUS_YIELD(); } + + this->resetCurrentParam(); + this->executeNow(); } #if defined(ERA_PNP_MODBUS) @@ -1108,6 +1172,7 @@ template void ERaModbus::sendModbusRead(ModbusConfig_t& param) { bool skip {false}; bool status {false}; + bool legacy {this->legacyProcess}; this->nextTransport(param); if (!this->failCounter.min) { @@ -1116,18 +1181,41 @@ void ERaModbus::sendModbusRead(ModbusConfig_t& param) { skip = true; } + if (!this->legacyProcess) { + legacy = !ModbusTransp::isNewReport(); + } switch (param.func) { case ModbusFunctionT::READ_COIL_STATUS: - status = ModbusTransp::readCoilStatus(this->transp, param); + if (legacy) { + status = ModbusTransp::readCoilStatusLegacy(this->transp, param); + } + else { + status = ModbusTransp::readCoilStatus(this->transp, param); + } break; case ModbusFunctionT::READ_INPUT_STATUS: - status = ModbusTransp::readInputStatus(this->transp, param); + if (legacy) { + status = ModbusTransp::readInputStatusLegacy(this->transp, param); + } + else { + status = ModbusTransp::readInputStatus(this->transp, param); + } break; case ModbusFunctionT::READ_HOLDING_REGISTERS: - status = ModbusTransp::readHoldingRegisters(this->transp, param); + if (legacy) { + status = ModbusTransp::readHoldingRegistersLegacy(this->transp, param); + } + else { + status = ModbusTransp::readHoldingRegisters(this->transp, param); + } break; case ModbusFunctionT::READ_INPUT_REGISTERS: - status = ModbusTransp::readInputRegisters(this->transp, param); + if (legacy) { + status = ModbusTransp::readInputRegistersLegacy(this->transp, param); + } + else { + status = ModbusTransp::readInputRegisters(this->transp, param); + } break; default: return; @@ -1139,6 +1227,8 @@ void ERaModbus::sendModbusRead(ModbusConfig_t& param) { if (skip) { } + else if (!ModbusTransp::canNextRequest()) { + } else if (!status) { this->failRead++; } @@ -1150,17 +1240,13 @@ bool ERaModbus::handlerModbusRead(ModbusConfig_t* param) { return false; } ERaGuardLock(this->mutex); - if (ModbusState::is(ModbusStateT::STATE_MB_PARSE) || - ModbusState::is(ModbusStateT::STATE_MB_CONTROLLED)) { + if (this->isStateUpdate()) { ERaGuardUnlock(this->mutex); - this->executeNow(); return false; } this->sendModbusRead(*param); this->delayModbus(param->addr, true); - if (ModbusState::is(ModbusStateT::STATE_MB_PARSE) || - ModbusState::is(ModbusStateT::STATE_MB_CONTROLLED)) { - this->executeNow(); + if (this->isStateUpdate()) { return false; } return true; @@ -1459,7 +1545,7 @@ bool ERaModbus::waitResponse(ERaModbusRequest* request, ERaModbusResponse* if (!ModbusStream::availableBytes()) { #if defined(ERA_NO_RTOS) if (this->runApiResponse) { - this->thisApi().run(); + this->thisApi().run(true); this->thisApi().runZigbee(); } #endif diff --git a/src/Modbus/ERaModbusTransp.hpp b/src/Modbus/ERaModbusTransp.hpp index 3168463..d956f49 100644 --- a/src/Modbus/ERaModbusTransp.hpp +++ b/src/Modbus/ERaModbusTransp.hpp @@ -712,65 +712,136 @@ class ERaModbusTransp { const char* TAG = "Modbus"; -public: + typedef bool (ERaModbusTransp::*ProcessFunc)( + ERaModbusRequest*, ERaModbusResponse*, ModbusConfig_t&, bool, bool + ); + +protected: ERaModbusTransp() + : currentRequest(nullptr) + , currentResponse(nullptr) + , lastRequestTime(0UL) {} ~ERaModbusTransp() {} - bool readCoilStatus(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { + bool readCoilStatus(const uint8_t transp, ModbusConfig_t& param) { + this->createCurrentRequest(transp, param); + return this->beforeProcess(&ERaModbusTransp::processRead, param); + } + + bool readInputStatus(const uint8_t transp, ModbusConfig_t& param) { + this->createCurrentRequest(transp, param); + return this->beforeProcess(&ERaModbusTransp::processRead, param); + } + + bool readHoldingRegisters(const uint8_t transp, ModbusConfig_t& param) { + this->createCurrentRequest(transp, param); + return this->beforeProcess(&ERaModbusTransp::processRead, param); + } + + bool readInputRegisters(const uint8_t transp, ModbusConfig_t& param) { + this->createCurrentRequest(transp, param); + return this->beforeProcess(&ERaModbusTransp::processRead, param); + } + + bool beforeProcess(ProcessFunc func, ModbusConfig_t& param) { + bool status {false}; + this->createCurrentResponse(); + + status = (this->*func)( + this->currentRequest, this->currentResponse, param, !this->lastRequestTime, false + ); + + this->deleteCurrentRequest(); + this->deleteCurrentResponse(); + return status; + } + + bool readCoilStatusLegacy(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { ERaModbusRequest* request = new_modbus ERaModbusRequest01(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processRead(request, param, skip); + return this->beforeProcessLegacy(&ERaModbusTransp::processRead, request, param, skip); } - bool readInputStatus(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { + bool readInputStatusLegacy(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { ERaModbusRequest* request = new_modbus ERaModbusRequest02(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processRead(request, param, skip); + return this->beforeProcessLegacy(&ERaModbusTransp::processRead, request, param, skip); } - bool readHoldingRegisters(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { + bool readHoldingRegistersLegacy(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { ERaModbusRequest* request = new_modbus ERaModbusRequest03(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processRead(request, param, skip); + return this->beforeProcessLegacy(&ERaModbusTransp::processRead, request, param, skip); } - bool readInputRegisters(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { + bool readInputRegistersLegacy(const uint8_t transp, ModbusConfig_t& param, bool skip = false) { ERaModbusRequest* request = new_modbus ERaModbusRequest04(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processRead(request, param, skip); + return this->beforeProcessLegacy(&ERaModbusTransp::processRead, request, param, skip); } bool forceSingleCoil(const uint8_t transp, ModbusConfig_t& param) { ERaModbusRequest* request = new_modbus ERaModbusRequest05(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processWrite(request); + return this->beforeProcessLegacy(&ERaModbusTransp::processWrite, request, param); } bool presetSingleRegister(const uint8_t transp, ModbusConfig_t& param) { ERaModbusRequest* request = new_modbus ERaModbusRequest06(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2)); - return this->processWrite(request); + return this->beforeProcessLegacy(&ERaModbusTransp::processWrite, request, param); } bool forceMultipleCoils(const uint8_t transp, ModbusConfig_t& param) { ERaModbusRequest* request = new_modbus ERaModbusRequest0F(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2), param.extra); - return this->processWrite(request); + return this->beforeProcessLegacy(&ERaModbusTransp::processWrite, request, param); } bool presetMultipleRegisters(const uint8_t transp, ModbusConfig_t& param) { ERaModbusRequest* request = new_modbus ERaModbusRequest10(transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2), param.extra); - return this->processWrite(request); + return this->beforeProcessLegacy(&ERaModbusTransp::processWrite, request, param); } - bool processRead(ERaModbusRequest* request, ModbusConfig_t& param, bool skip = false) { + bool beforeProcessLegacy(ProcessFunc func, ERaModbusRequest* request, + ModbusConfig_t& param, bool skip = false) { bool status {false}; ERA_ASSERT_NULL(request, false) ERaModbusResponse* response = new_modbus ERaModbusResponse(request, request->responseLength()); - ERA_ASSERT_NULL(response, false) + ERA_ASSERT_NULL_DEL(response, false, request) + + status = (this->*func)(request, response, param, false, skip); + + delete request; + delete response; + request = nullptr; + response = nullptr; + return status; + } + + bool processRead(ERaModbusRequest* request, ERaModbusResponse* response, + ModbusConfig_t& param, bool sendOnly = false, bool skip = false) { + if ((request == nullptr) || (response == nullptr)) { + return false; + } + + bool status {false}; + + if (!this->lastRequestTime) { + } + else if (this->thisModbus().availableBytes()) { + } + else if ((ERaMillis() - this->lastRequestTime) >= this->thisModbus().timeout) { + this->lastRequestTime = 0UL; + return false; + } + else { + return false; + } + if (ERaModbusInternal::handlerRead(request, response, status)) { this->thisModbus().updateTotalRead(); ERaLogHex("IB <<", response->getMessage(), response->getSize()); @@ -782,9 +853,10 @@ class ERaModbusTransp request->getSlaveAddress(), param.totalFail); } else { - this->thisModbus().updateTotalRead(); - this->thisModbus().sendRequest(request->getMessage(), request->getSize()); - status = this->thisModbus().waitResponse(request, response); + status = this->sendRequestAndWaitResponse(request, response, sendOnly); + if (sendOnly) { + return status; + } } if (status) { param.totalFail = 0; @@ -799,16 +871,13 @@ class ERaModbusTransp if (param.totalFail >= this->thisModbus().failCounter.max) { param.totalFail = this->thisModbus().failCounter.start; } - delete request; - delete response; + this->lastRequestTime = 0UL; return status; } - bool processWrite(ERaModbusRequest* request) { + bool processWrite(ERaModbusRequest* request, ERaModbusResponse* response, + ModbusConfig_t& param, bool sendOnly = false, bool skip = false) { bool status {false}; - ERA_ASSERT_NULL(request, false) - ERaModbusResponse* response = new_modbus ERaModbusResponse(request, request->responseLength()); - ERA_ASSERT_NULL(response, false) this->thisModbus().updateTotalWrite(); if (ERaModbusInternal::handlerWrite(request, response, status)) { ERaLogHex("IB <<", request->getMessage(), request->getSize()); @@ -822,12 +891,82 @@ class ERaModbusTransp } } } - delete request; - delete response; + ERA_FORCE_UNUSED(param); + ERA_FORCE_UNUSED(skip); + ERA_FORCE_UNUSED(skip); return status; } + bool canNextRequest() const { + return (this->lastRequestTime == 0UL); + } + + void reset() { + this->deleteCurrentRequest(); + this->deleteCurrentResponse(); + this->lastRequestTime = 0UL; + } + private: + bool sendRequestAndWaitResponse(ERaModbusRequest* request, ERaModbusResponse* response, bool sendOnly) { + bool status {false}; + if (!this->lastRequestTime) { + this->thisModbus().updateTotalRead(); + this->thisModbus().sendRequest(request->getMessage(), request->getSize()); + this->lastRequestTime = ERaMillis(); + } + if (!sendOnly) { + status = this->thisModbus().waitResponse(request, response); + } + return status; + } + + template + void createCurrentRequest(const uint8_t transp, const ModbusConfig_t& param) { + if (this->currentRequest != nullptr) { + return; + } + this->currentRequest = new_modbus T( + transp, param.addr, BUILD_WORD(param.sa1, param.sa2), BUILD_WORD(param.len1, param.len2) + ); + } + + void deleteCurrentRequest() { + if (this->lastRequestTime) { + return; + } + if (this->currentRequest == nullptr) { + return; + } + delete this->currentRequest; + this->currentRequest = nullptr; + } + + void createCurrentResponse() { + if (this->currentResponse != nullptr) { + return; + } + ERA_ASSERT_NULL(this->currentRequest, this->dummy()) + this->currentResponse = new_modbus ERaModbusResponse( + this->currentRequest, this->currentRequest->responseLength() + ); + ERA_ASSERT_NULL_DEL(this->currentResponse, this->dummy(), this->currentRequest) + } + + void deleteCurrentResponse() { + if (this->lastRequestTime) { + return; + } + if (this->currentResponse == nullptr) { + return; + } + delete this->currentResponse; + this->currentResponse = nullptr; + } + + void dummy() { + } + inline const Modbus& thisModbus() const { return static_cast(*this); @@ -838,6 +977,9 @@ class ERaModbusTransp return static_cast(*this); } + ERaModbusRequest* currentRequest; + ERaModbusResponse* currentResponse; + unsigned int lastRequestTime; }; #endif /* INC_ERA_MODBUS_TRANSPORT_HPP_ */ diff --git a/src/Zigbee/ERaDBZigbee.hpp b/src/Zigbee/ERaDBZigbee.hpp index e283db1..4d508ab 100644 --- a/src/Zigbee/ERaDBZigbee.hpp +++ b/src/Zigbee/ERaDBZigbee.hpp @@ -35,6 +35,8 @@ class ERaDBZigbee void parseConfigMapZigbee(const cJSON* const root); void parseConfigMapDevices(const cJSON* const root); + void processConfigMapZigbee(cJSON* root, const char* hash, const char* buf); + void parseZigbeeDevice(); void storeZigbeeDevice(); IdentDeviceAddr_t* getDeviceFromCoordinator(); @@ -255,6 +257,17 @@ void ERaDBZigbee::parseZigbeeConfig(const char* str) { item = nullptr; } +template +void ERaDBZigbee::processConfigMapZigbee(cJSON* root, const char* hash, const char* buf) { + if (!this->updateHashID(hash, true)) { + return; + } + + this->parseConfigMapDevices(root); + this->storeZigbeeConfig(buf); + ERaWriteConfig(ERaConfigTypeT::ERA_ZIGBEE_CONFIG); +} + template void ERaDBZigbee::storeZigbeeConfig(const char* str) { if (str == nullptr) { diff --git a/src/Zigbee/definition/ERaDefineZigbee.hpp b/src/Zigbee/definition/ERaDefineZigbee.hpp index 6daf102..0be9fce 100644 --- a/src/Zigbee/definition/ERaDefineZigbee.hpp +++ b/src/Zigbee/definition/ERaDefineZigbee.hpp @@ -43,6 +43,12 @@ #define ZIGBEE_PUBLISH_RETAINED true #endif +#if defined(ZIGBEE_DECIMAL_VALUE) + /* OK, use the specified value */ +#else + #define ZIGBEE_DECIMAL_VALUE 5 +#endif + #define NO_NWK_ADDR (uint16_t)0x0000 #define NO_LOAD_ENDPOINT (uint8_t)0xFF #define ZCL_DATA_MIN 3 diff --git a/src/Zigbee/fromZigbee/ERaFromData.hpp b/src/Zigbee/fromZigbee/ERaFromData.hpp index d12887b..e50a60b 100644 --- a/src/Zigbee/fromZigbee/ERaFromData.hpp +++ b/src/Zigbee/fromZigbee/ERaFromData.hpp @@ -259,11 +259,11 @@ void ERaFromZigbee::addDataZigbee(const DataAFMsg_t& afMsg, cJSON* root, } } if (afMsg.srcAddr.endpoint == EndpointListT::ENDPOINT1) { - cJSON_SetNumberWithDecimalToObject(root, key, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, key, value * scale, ZIGBEE_DECIMAL_VALUE); } else { StringPrint(name, "%s_%d", key, afMsg.srcAddr.endpoint); - cJSON_SetNumberWithDecimalToObject(root, name, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, name, value * scale, ZIGBEE_DECIMAL_VALUE); } return; } @@ -307,11 +307,11 @@ void ERaFromZigbee::addDataZigbee(const DataAFMsg_t& afMsg, cJSON* root, } #endif if (afMsg.srcAddr.endpoint == EndpointListT::ENDPOINT1) { - cJSON_SetNumberWithDecimalToObject(root, key, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, key, value * scale, ZIGBEE_DECIMAL_VALUE); } else { StringPrint(name, "%s_%d", key, afMsg.srcAddr.endpoint); - cJSON_SetNumberWithDecimalToObject(root, name, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, name, value * scale, ZIGBEE_DECIMAL_VALUE); } } @@ -345,11 +345,11 @@ void ERaFromZigbee::addDataZigbee(const DataAFMsg_t& afMsg, cJSON* root, } #endif if (afMsg.srcAddr.endpoint == EndpointListT::ENDPOINT1) { - cJSON_SetNumberWithDecimalToObject(root, key, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, key, value * scale, ZIGBEE_DECIMAL_VALUE); } else { StringPrint(name, "%s_%d", key, afMsg.srcAddr.endpoint); - cJSON_SetNumberWithDecimalToObject(root, name, value * scale, 5); + cJSON_SetNumberWithDecimalToObject(root, name, value * scale, ZIGBEE_DECIMAL_VALUE); } }