diff --git a/apps/aqhome-cgi/modules/mdevices.c b/apps/aqhome-cgi/modules/mdevices.c index baca810..3b57ca0 100644 --- a/apps/aqhome-cgi/modules/mdevices.c +++ b/apps/aqhome-cgi/modules/mdevices.c @@ -55,10 +55,14 @@ static void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQ static void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); static void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); -static void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf); -static void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf); +static void _writeValueListToTable(AQH_DATACLIENT *dc, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf); +static void _writeValueToTable(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf); static void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf); static uint32_t _colorFromHexString(const char *s); +static void _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); +static void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); +static void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); +static void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf); @@ -309,7 +313,7 @@ void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATA GBAS(dbuf,"
\n"); GBAA(dbuf, "\n", sDeviceName); - _writeValueListToTable(valueList, dbuf); + _writeValueListToTable(dc, valueList, dbuf); GBAS(dbuf,""); GBAS(dbuf, "
\n\n"); @@ -341,86 +345,17 @@ void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DAT value=AQH_Value_List_First(valueList); while(value) { if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { - const char *sValueSystemName; const char *sValueName; const char *sValue; - int rv; - sValueSystemName=AQH_Value_GetNameForSystem(value); sValueName=AQH_Value_GetName(value); sValue=GWEN_DB_GetCharValue(dbPost, sValueName, 0, NULL); if (sValueName && *sValueName) { DBG_ERROR(NULL, "Setting value %s to %s", sValueName?sValueName:"no name", sValue?sValue:"no value"); switch(AQH_Value_GetModality(value)) { - case AQH_ValueModality_RGBW: - if (sValue) { - uint32_t color; - char colbuf[16]; - - color=_colorFromHexString(sValue); - snprintf(colbuf, sizeof(colbuf), "0x%08x", color); - DBG_ERROR(NULL, "Send value [%s] to %s", colbuf, sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, colbuf); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - GBAA(dbuf, "

Error setting value for %s

", sValueSystemName); - } - } - break; - case AQH_ValueModality_OnOff: - if (sValue) { - if (strcasecmp(sValue, "unchanged")==0) { - DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); - } - else if (strcasecmp(sValue, "on")==0) { - DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "1"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "off")==0) { - DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "0"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else { - } - } - break; - case AQH_ValueModality_OnOffAuto: - if (sValue) { - if (strcasecmp(sValue, "unchanged")==0) { - DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); - } - else if (strcasecmp(sValue, "on")==0) { - DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "1"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "off")==0) { - DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "0"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "auto")==0) { - DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "2"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else { - DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName); - } - } - break; + case AQH_ValueModality_RGBW: _setRgbwData(dc, value, sValue); break; + case AQH_ValueModality_OnOff: _setOnOffData(dc, value, sValue); break; + case AQH_ValueModality_OnOffAuto: _setOnOffAutoData(dc, value, sValue); break; default: break; } /* switch */ @@ -428,10 +363,8 @@ void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DAT } value=AQH_Value_List_Next(value); } /* while */ - - } - AQH_Value_List_free(valueList); + AQH_Value_List_free(valueList); if (sDeviceName && *sDeviceName) { GWEN_BUFFER *pbuf; @@ -448,7 +381,7 @@ void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DAT -void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) +void _writeValueListToTable(AQH_DATACLIENT *dc, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) { const AQH_VALUE *value; @@ -471,7 +404,7 @@ void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) value=AQH_Value_List_First(valueList); while(value) { - _writeValueToTable(value, dbuf); + _writeValueToTable(dc, value, dbuf); value=AQH_Value_List_Next(value); } GBAS(dbuf, @@ -481,7 +414,7 @@ void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) -void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf) +void _writeValueToTable(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf) { const char *s; @@ -508,8 +441,7 @@ void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf) #endif GBAS(dbuf, ""); - if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) - _addValueActionToForm(value, dbuf); + _addLastValueToForm(dc, value, dbuf); GBAS(dbuf, ""); GBAA(dbuf, "\n"); @@ -579,6 +511,148 @@ uint32_t _colorFromHexString(const char *s) +void _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) +{ + if (sValue) { + const char *sValueSystemName; + uint32_t color; + int rv; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + color=_colorFromHexString(sValue); + DBG_ERROR(NULL, "Send value [#%08x] to %s", color, sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, (double) color); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } +} + + + +void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) +{ + if (sValue) { + const char *sValueSystemName; + int rv; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + if (strcasecmp(sValue, "unchanged")==0) { + DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); + } + else if (strcasecmp(sValue, "on")==0) { + DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 1.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "off")==0) { + DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 0.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else { + } + } +} + + + +void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) +{ + if (sValue) { + const char *sValueSystemName; + int rv; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + if (strcasecmp(sValue, "unchanged")==0) { + DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); + } + else if (strcasecmp(sValue, "on")==0) { + DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 1.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "off")==0) { + DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 0.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "auto")==0) { + DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 2.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else { + DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName); + } + } +} + + + +void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueSystemName; + const char *sValueName; + uint64_t dataPoints[2]; + uint64_t recvdNum; +// uint64_t timestamp; + union {double f; uint64_t i;} u; + int intVal; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + sValueName=AQH_Value_GetName(value); + recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1); + if (recvdNum>0) { +// timestamp=dataPoints[0]; + u.i=dataPoints[1]; + intVal=(int) u.f; + } + else { + u.i=0; + intVal=-1; + } + + if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { + DBG_ERROR(NULL, "Adding actor"); + switch(AQH_Value_GetModality(value)) { + case AQH_ValueModality_RGBW: + GBAA(dbuf, "", sValueName, (unsigned int) u.f); + break; + case AQH_ValueModality_OnOff: + GBAA(dbuf, ""); + break; + case AQH_ValueModality_OnOffAuto: + GBAA(dbuf, ""); + break; + default: +// GBAA(dbuf, "", sValueName, u.f); + GBAA(dbuf, "%.2f", u.f); + break; + } /* switch */ + } /* if actor */ + else { + DBG_ERROR(NULL, "Adding sensor (%s=%.2f)", sValueName, u.f); + GBAA(dbuf, "%.2f", u.f); + } +} diff --git a/apps/aqhome-data/s_setdata.c b/apps/aqhome-data/s_setdata.c index a80e113..aa4360b 100644 --- a/apps/aqhome-data/s_setdata.c +++ b/apps/aqhome-data/s_setdata.c @@ -42,14 +42,15 @@ * ------------------------------------------------------------------------------------------------ */ +static void _storeDatapoint(AQHOME_SERVER *xo, const AQH_VALUE *v, double valueData); static AQH_MSG_REQUEST *_mkRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, uint32_t requestMsgId, AQH_OBJECT *epDriver, - const AQH_VALUE *v, const char *data); + const AQH_VALUE *v, double data); static void _rqSubRequestFinished(AQH_MSG_REQUEST *rq, AQH_MSG_REQUEST *subRq, int reason); static void _rqAbort(AQH_MSG_REQUEST *rq, int reason); -static AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, const char *data); +static AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, double data); static int _subRqHandleResponse(AQH_MSG_REQUEST *rq, const AQH_MESSAGE *msg); static void _subRqAbort(AQH_MSG_REQUEST *rq, int reason); @@ -76,11 +77,11 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ recvdValue=AQH_IpcdMessageSetData_ReadValue(tagList); if (recvdValue) { const char *valueName; - char *valueDataFreeable; + double valueData; AQH_VALUE *systemValue; valueName=AQH_Value_GetNameForSystem(recvdValue); - valueDataFreeable=AQH_IpcdMessageSetData_ReadData(tagList); + valueData=AQH_IpcdMessageSetData_ReadData(tagList); systemValue=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName); if (systemValue) { @@ -96,8 +97,10 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AQH_MSG_REQUEST *rq; DBG_ERROR(NULL, "Creating SETDATA request for driver endpoint (%s)", AQH_Endpoint_GetServiceName(epDriver)); - rq=_mkRequest_SetData(o, epSrc, msgId, epDriver, systemValue, valueDataFreeable); + rq=_mkRequest_SetData(o, epSrc, msgId, epDriver, systemValue, valueData); AqHomeDataServer_AddRequestToTree(o, rq); + + _storeDatapoint(xo, systemValue, valueData); } else { DBG_ERROR(NULL, "Driver \"%s\" not available", driverName); @@ -119,7 +122,6 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AqHomeDataServer_SendResponseResultToEndpoint(epSrc, msgId, AQH_MSGDATA_RESULT_ERROR_NOTFOUND); } AQH_Value_free(recvdValue); - free(valueDataFreeable); } /* if recvdValue */ else { DBG_ERROR(NULL, "No value in message"); @@ -131,6 +133,23 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ +void _storeDatapoint(AQHOME_SERVER *xo, const AQH_VALUE *v, double valueData) +{ + uint64_t timestamp; + int rv; + + timestamp=(uint64_t) time(NULL); + rv=AQH_Storage_AddDatapoint(xo->storage, AQH_Value_GetId(v), timestamp, valueData); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + } + else { + DBG_INFO(NULL, "Datapoint added for value \"%s\"", AQH_Value_GetNameForSystem(v)); + } +} + + + /* ------------------------------------------------------------------------------------------------ * IPC Request SETDATA */ @@ -138,7 +157,7 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AQH_MSG_REQUEST *_mkRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, uint32_t requestMsgId, AQH_OBJECT *epDriver, - const AQH_VALUE *v, const char *data) + const AQH_VALUE *v, double data) { AQH_MSG_REQUEST *rq; AQH_MSG_REQUEST *subRq; @@ -205,7 +224,7 @@ void _rqAbort(AQH_MSG_REQUEST *rq, int reason) */ -AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, const char *data) +AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, double data) { AQH_MSG_REQUEST *rq; uint16_t msgId; diff --git a/apps/aqhome-mqttlog/s_setdata.c b/apps/aqhome-mqttlog/s_setdata.c index 13aa5ea..74f1b05 100644 --- a/apps/aqhome-mqttlog/s_setdata.c +++ b/apps/aqhome-mqttlog/s_setdata.c @@ -30,8 +30,13 @@ */ static void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, - const char *valueName, const char *valueData); -static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData); + const char *valueName, double valueData); +static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, + const AQHMQTT_DEVICE *device, + const AQHMQTT_TOPIC *topic, + const AQHMQTT_VALUE *value, + double valueData); +static const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double valueData); static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic); @@ -65,12 +70,11 @@ void AQH_MqttLogServer_HandleSetData(AQH_OBJECT *o, device=AQH_MqttLogServer_FindRegisteredDevice(o, deviceName); if (device) { - char *valueDataFreeable; + double valueData; DBG_ERROR(NULL, "Sending data to value \"%s\" of device \"%s\"", valueName, deviceName); - valueDataFreeable=AQH_IpcdMessageSetData_ReadData(tagList); - _sendDataForDevice(xo, device, valueName, valueDataFreeable); - free(valueDataFreeable); + valueData=AQH_IpcdMessageSetData_ReadData(tagList); + _sendDataForDevice(xo, device, valueName, valueData); } else { DBG_ERROR(NULL, "Device \"%s\" not found", deviceName); @@ -93,7 +97,7 @@ void AQH_MqttLogServer_HandleSetData(AQH_OBJECT *o, void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, - const char *valueName, const char *valueData) + const char *valueName, double valueData) { const char *deviceId; @@ -116,7 +120,7 @@ void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, if (value) { /* found value, create publish msg, send */ DBG_ERROR(NULL, "Topic \"%s\" contains value \"%s\"", AQHMQTT_Topic_GetName(topic), valueName); - _sendValueToMqtt(xo, deviceId, topic, valueData); + _sendValueToMqtt(xo, device, topic, value, valueData); } } /* if out */ topic=AQHMQTT_Topic_List_Next(topic); @@ -130,32 +134,72 @@ void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, -void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData) +void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, + const AQHMQTT_DEVICE *device, + const AQHMQTT_TOPIC *topic, + const AQHMQTT_VALUE *value, + double valueData) { + const char *deviceId; + const char *translatedValue; GWEN_BUFFER *buf; #if !DEBUG_DRY_RUN AQH_MESSAGE *msgOut; #endif + deviceId=AQHMQTT_Device_GetId(device); buf=_createBufferForTopic(deviceId, topic); + translatedValue=_valueTranslatedForDriver(value, valueData); + if (translatedValue && *translatedValue) { + DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), translatedValue); + msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), (const uint8_t*)translatedValue, strlen(translatedValue)); + } + else { + GWEN_BUFFER *vbuf; + + vbuf=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Buffer_AppendArgs(vbuf, "%f", valueData); + DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetStart(vbuf)); + msgOut=AQH_MqttMessagePublish_new(0, 0, + GWEN_Buffer_GetStart(buf), + (const uint8_t*)GWEN_Buffer_GetStart(vbuf), + GWEN_Buffer_GetUsedBytes(vbuf)); + GWEN_Buffer_free(vbuf); + } + #if !DEBUG_DRY_RUN - DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); - msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), - (const uint8_t*) (valueData?valueData:NULL), - valueData?strlen(valueData):0); if (msgOut) AQH_Endpoint_AddMsgOut(xo->mqttEndpoint, msgOut); else { DBG_ERROR(NULL, "Error creating message"); } -#else - DBG_ERROR(NULL, "Would MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); #endif GWEN_Buffer_free(buf); } +const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double valueData) +{ + const AQHMQTT_TRANSLATION_LIST *translationList; + + translationList=AQHMQTT_Value_GetTranslationList(value); + if (translationList) { + const AQHMQTT_TRANSLATION *t; + int valueAsInt; + + valueAsInt=(int) valueData; + t=AQHMQTT_Translation_List_GetByAqhValue(translationList, valueAsInt); + if (t) { + return AQHMQTT_Translation_GetDriverValue(t); + } + } + + return NULL; +} + + + GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic) { GWEN_BUFFER *buf; diff --git a/apps/aqhome-mqttlog/types/translation.t2d b/apps/aqhome-mqttlog/types/translation.t2d index ce1d4dc..edf5e6c 100644 --- a/apps/aqhome-mqttlog/types/translation.t2d +++ b/apps/aqhome-mqttlog/types/translation.t2d @@ -32,18 +32,18 @@ - + 0 0 public - own + with_getByMember 0 0 public - own + own with_getByMember diff --git a/apps/aqhome-mqttlog/xmlread.c b/apps/aqhome-mqttlog/xmlread.c index 06649b1..ddb19bd 100644 --- a/apps/aqhome-mqttlog/xmlread.c +++ b/apps/aqhome-mqttlog/xmlread.c @@ -458,16 +458,16 @@ AQHMQTT_TRANSLATION_LIST *_readXmlTranslationList(GWEN_XMLNODE *parentNode) AQHMQTT_TRANSLATION *_readXmlTranslation(GWEN_XMLNODE *translationNode) { - const char *sAqhValue; + int aqhValue; const char *sDriverValue; - sAqhValue=GWEN_XMLNode_GetProperty(translationNode, "aqhValue", NULL); + aqhValue=GWEN_XMLNode_GetIntProperty(translationNode, "aqhValue", 0); sDriverValue=GWEN_XMLNode_GetProperty(translationNode, "driverValue", NULL); - if (sAqhValue && *sAqhValue && sDriverValue && *sDriverValue) { + if (sDriverValue && *sDriverValue) { AQHMQTT_TRANSLATION *translation; translation=AQHMQTT_Translation_new(); - AQHMQTT_Translation_SetAqhValue(translation, sAqhValue); + AQHMQTT_Translation_SetAqhValue(translation, aqhValue); AQHMQTT_Translation_SetDriverValue(translation, sDriverValue); return translation; } diff --git a/apps/aqhome-mqttlog/xmlwrite.c b/apps/aqhome-mqttlog/xmlwrite.c index d6ea5ea..af56843 100644 --- a/apps/aqhome-mqttlog/xmlwrite.c +++ b/apps/aqhome-mqttlog/xmlwrite.c @@ -222,7 +222,7 @@ void _writeValueToXml(const AQHMQTT_VALUE *value, GWEN_XMLNODE *node) void _writeTranslationToXml(const AQHMQTT_TRANSLATION *t, GWEN_XMLNODE *nTranslation) { - _setXmlPropertyIfNotNull(nTranslation, "aqhValue", AQHMQTT_Translation_GetAqhValue(t)); + GWEN_XMLNode_SetIntProperty(nTranslation, "aqhValue", AQHMQTT_Translation_GetAqhValue(t)); _setXmlPropertyIfNotNull(nTranslation, "driverValue", AQHMQTT_Translation_GetDriverValue(t)); } diff --git a/apps/aqhome-nodes/r_setdata.c b/apps/aqhome-nodes/r_setdata.c index 9ad5a22..6a38c66 100644 --- a/apps/aqhome-nodes/r_setdata.c +++ b/apps/aqhome-nodes/r_setdata.c @@ -92,7 +92,7 @@ void AQH_NodeServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA varName=AQH_Value_GetName(value); if (varName) { - char *data; + double data; data=AQH_IpcdMessageSetData_ReadData(tagList); if (data) { @@ -115,7 +115,7 @@ void AQH_NodeServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA uint16_t dataVal=0; uint16_t dataDenom=0; - if (AQH_ReadDataFromString(AQHNODE_Value_GetDataType(devValue), data, &dataVal, &dataDenom)==0) { + if (AQH_ReadDataFromDouble(AQHNODE_Value_GetDataType(devValue), data, &dataVal, &dataDenom)==0) { AQH_MSG_REQUEST *rq; int destAddr; @@ -150,7 +150,6 @@ void AQH_NodeServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA DBG_ERROR(NULL, "No matching nodeinfo"); _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); } - free(data); } else { DBG_ERROR(NULL, "No data"); diff --git a/apps/aqhome-react/examples/001-tvlight.xml b/apps/aqhome-react/examples/001-tvlight.xml index 707e5a3..b8e7ec6 100644 --- a/apps/aqhome-react/examples/001-tvlight.xml +++ b/apps/aqhome-react/examples/001-tvlight.xml @@ -26,15 +26,6 @@ - - - OFF - OFF - ON - - - - mqtt/109C2F/power @@ -49,7 +40,6 @@ - - + diff --git a/apps/aqhome-react/networks/delayedoff.xml b/apps/aqhome-react/networks/delayedoff.xml index ec1fe52..587b201 100644 --- a/apps/aqhome-react/networks/delayedoff.xml +++ b/apps/aqhome-react/networks/delayedoff.xml @@ -12,7 +12,7 @@ - + diff --git a/apps/aqhome-react/types/prgrule.c b/apps/aqhome-react/types/prgrule.c index 8dcca13..a572687 100644 --- a/apps/aqhome-react/types/prgrule.c +++ b/apps/aqhome-react/types/prgrule.c @@ -312,10 +312,29 @@ const char *_readValueAndProbablyRange(const char *s, uint64_t *ptrBitField, int { int v=0; - while(isdigit(*s)) { - v*=10; - v+=(*s)-'0'; - s++; + if (*s=='#') { + while(*s) { + unsigned char c; + + c=tolower(*s); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + c-='0'; + if (c>9) + c-=7; + v<<=4; + v+=c; + } + else + break; + s++; + } + } + else { + while(isdigit(*s)) { + v*=10; + v+=(*s)-'0'; + s++; + } } if (!_valueOkay(v, minValue, maxValue)) { DBG_INFO(NULL, "here"); diff --git a/apps/aqhome-react/units/u_valueset.c b/apps/aqhome-react/units/u_valueset.c index 2ac6fd4..4643174 100644 --- a/apps/aqhome-react/units/u_valueset.c +++ b/apps/aqhome-react/units/u_valueset.c @@ -38,7 +38,6 @@ */ static void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject); -static AQH_MESSAGE *_mkSetDataMsgString(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); static AQH_MESSAGE *_mkSetDataMsgDouble(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); @@ -62,12 +61,12 @@ AQHREACT_UNIT *AqHomeReact_UnitValueSet_new(AQH_OBJECT *aqh) port=AQHREACT_Port_new(); AQHREACT_Port_SetName(port, "input"); AQHREACT_Port_SetIdForUnit(port, AQHOMEREACT_UNIT_VALUESET_INSLOT_VALUE); - AQHREACT_Port_SetDataType(port, AQHREACT_DATAOBJECTTYPE_STRING); + AQHREACT_Port_SetDataType(port, AQHREACT_DATAOBJECTTYPE_DOUBLE); AQHREACT_Unit_AddInputPort(unit, port); param=AQHREACT_Param_new(); AQHREACT_Param_SetName(param, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUENAME); - AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_STRING); + AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_DOUBLE); AQHREACT_Unit_AddParam(unit, param); return unit; @@ -92,9 +91,6 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO case AQHREACT_DATAOBJECTTYPE_DOUBLE: msgOut=_mkSetDataMsgDouble(brokerEndpoint, sValueName, dataObject); break; - case AQHREACT_DATAOBJECTTYPE_STRING: - msgOut=_mkSetDataMsgString(brokerEndpoint, sValueName, dataObject); - break; default: DBG_ERROR(NULL, "Unhandled data type (%d)", AQHREACT_DataObject_GetDataType(dataObject)); msgOut=NULL; @@ -130,47 +126,21 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO -AQH_MESSAGE *_mkSetDataMsgString(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) -{ - AQH_MESSAGE *msgOut; - AQH_VALUE *v; - - v=AQH_Value_new(); - AQH_Value_SetNameForSystem(v, sValueName); - - msgOut=AQH_IpcdMessageSetData_new(AQH_MSGTYPE_IPC_DATA_SETDATA, - AQH_Endpoint_GetNextMessageId(brokerEndpoint), 0, - v, AQHREACT_DataObject_GetStringData(dataObject)); - AQH_Value_free(v); - return msgOut; -} - - - AQH_MESSAGE *_mkSetDataMsgDouble(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) { AQH_MESSAGE *msgOut; AQH_VALUE *v; double data; - GWEN_BUFFER *buf; int rv; v=AQH_Value_new(); AQH_Value_SetNameForSystem(v, sValueName); data=AQHREACT_DataObject_GetDoubleData(dataObject); - buf=GWEN_Buffer_new(0, 64, 0, 1); - rv=GWEN_Text_DoubleToBuffer(data, buf); - if (rv<0) { - GWEN_Buffer_free(buf); - AQH_Value_free(v); - return NULL; - } msgOut=AQH_IpcdMessageSetData_new(AQH_MSGTYPE_IPC_DATA_SETDATA, AQH_Endpoint_GetNextMessageId(brokerEndpoint), 0, - v, GWEN_Buffer_GetStart(buf)); - GWEN_Buffer_free(buf); + v, data); AQH_Value_free(v); return msgOut; } diff --git a/apps/aqhome-tool/data/setdata.c b/apps/aqhome-tool/data/setdata.c index 2faee5a..e2b2024 100644 --- a/apps/aqhome-tool/data/setdata.c +++ b/apps/aqhome-tool/data/setdata.c @@ -45,6 +45,7 @@ */ static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId); +static int _readValueFromString(const char *s, double *pDouble); @@ -93,18 +94,30 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId) GWEN_DB_NODE *dbArgs; const char *valueName; const char *valueUnits; - const char *valueData; + const char *valueDataAsString; + double valueData; AQH_VALUE *v; + int rv; dbArgs=AQH_ToolClient_GetDbLocalArgs(o); valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL); valueUnits=GWEN_DB_GetCharValue(dbArgs, "valueUnits", 0, NULL); - valueData=GWEN_DB_GetCharValue(dbArgs, "value", 0, NULL); + valueDataAsString=GWEN_DB_GetCharValue(dbArgs, "value", 0, NULL); + + if (valueDataAsString && *valueDataAsString) { + rv=_readValueFromString(valueDataAsString, &valueData); + if (rv<0) { + DBG_ERROR(NULL, "ERROR: Bad value"); + return NULL; + } + } + if (!(valueName && *valueName)) { DBG_ERROR(NULL, "ERROR: Missing value name"); return NULL; } + v=AQH_Value_new(); AQH_Value_SetNameForSystem(v, valueName); AQH_Value_SetValueUnits(v, valueUnits); @@ -116,3 +129,40 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId) +int _readValueFromString(const char *s, double *pDouble) +{ + int l; + + l=strlen(s); + if (l) { + if (*s=='#') { + unsigned int h; + + if (1==sscanf(s+1, "%x", &h)) { + *pDouble=(double) h; + return 0; + } + } + else if (l>1 && s[0]=='0' && ((tolower(s[1])=='x') || tolower(s[1])=='b')) { + unsigned int h; + + if (1==sscanf(s, "%u", &h)) { + *pDouble=(double) h; + return 0; + } + } + else { + double d; + + if (1==sscanf(s, "%lf", &d)) { + return d; + } + } + DBG_ERROR(NULL, "Bad value \"%s\"", s); + return GWEN_ERROR_GENERIC; + } +} + + + + diff --git a/aqhome/aqhome.c b/aqhome/aqhome.c index bee2f17..39ff339 100644 --- a/aqhome/aqhome.c +++ b/aqhome/aqhome.c @@ -43,6 +43,10 @@ static void _definePath(const char *pathName, const char *pathValue); static GWEN_STRINGLIST *_getListOfMatchingFiles(const char *pathName, const char *subFolder, const char *mask); static GWEN_BUFFER *_getRuntimeFilePath(const char *pathName, const char *sFilename); static GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename); +static int _readUint8DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); +static int _readUint16DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); +static int _readUint32DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); + static int _readUint8DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint16DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint32DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); @@ -469,6 +473,59 @@ GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename) +int AQH_ReadDataFromDouble(int dataType, double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + switch(dataType) { + case AQH_ValueDataType_Uint8: return _readUint8DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Int: + case AQH_ValueDataType_Uint16: return _readUint16DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Uint32: return _readUint32DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Rational: break; + default: break; + } + + return GWEN_ERROR_INVALID; +} + + + +int _readUint8DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint8_t v; + + v=((uint8_t) (d)) & 0xff; + *pDataVal=v & 0xff; + *pDataDenom=1; + return 0; +} + + + +int _readUint16DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint16_t v; + + v=((uint16_t) d) & 0xffff; + *pDataVal=v; + *pDataDenom=1; + return 0; +} + + + +int _readUint32DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint32_t v; + + v=((uint32_t) d) & 0xffffffff; + + *pDataVal=(v>>16) & 0xffff; + *pDataDenom=v & 0xffff; + return 0; +} + + + int AQH_ReadDataFromString(int dataType, const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { if (s && *s) { diff --git a/aqhome/aqhome.h b/aqhome/aqhome.h index d86f540..ff159af 100644 --- a/aqhome/aqhome.h +++ b/aqhome/aqhome.h @@ -84,6 +84,7 @@ AQHOME_API int AQH_ValueModality_fromString(const char *s); AQHOME_API const char *AQH_ValueModality_toString(int i); AQHOME_API int AQH_ReadDataFromString(int dataType, const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); +AQHOME_API int AQH_ReadDataFromDouble(int dataType, double d, uint16_t *pDataVal, uint16_t *pDataDenom); #endif diff --git a/aqhome/dataclient/client.c b/aqhome/dataclient/client.c index 9b6336e..7d94c39 100644 --- a/aqhome/dataclient/client.c +++ b/aqhome/dataclient/client.c @@ -343,7 +343,7 @@ uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char *valueName, -int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, const char *data) +int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, double data) { if (dc) { AQH_MESSAGE *msgOut; diff --git a/aqhome/dataclient/client.h b/aqhome/dataclient/client.h index 1a77195..f6071ac 100644 --- a/aqhome/dataclient/client.h +++ b/aqhome/dataclient/client.h @@ -43,7 +43,7 @@ AQHOME_API uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char uint64_t *dataPtr, uint64_t maxNum, uint64_t tsBegin, uint64_t tsEnd); -AQHOME_API int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, const char *data); +AQHOME_API int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, double data); AQHOME_API int AQH_DataClient_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t timeStamp, double dataPoint); diff --git a/aqhome/msg/ipc/data/m_ipcd_setdata.c b/aqhome/msg/ipc/data/m_ipcd_setdata.c index 63b71a5..ea0f85b 100644 --- a/aqhome/msg/ipc/data/m_ipcd_setdata.c +++ b/aqhome/msg/ipc/data/m_ipcd_setdata.c @@ -37,7 +37,7 @@ AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, - const AQH_VALUE *value, const char *data) + const AQH_VALUE *value, double data) { AQH_MESSAGE *msg; GWEN_BUFFER *buf; @@ -51,8 +51,7 @@ AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, GWEN_Buffer_free(buf); return NULL; } - if (data && *data) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SET_TAGS_DATA, data, buf); + GWEN_Tag16_WriteDoubleTagToBuffer(AQH_MSGDATA_SET_TAGS_DATA, data, buf); msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId, GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf)); @@ -78,9 +77,9 @@ AQH_VALUE *AQH_IpcdMessageSetData_ReadValue(const GWEN_TAG16_LIST *tagList) -char *AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList) +double AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList) { - return AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_SET_TAGS_DATA, NULL); + return AQH_Tag16_GetTagDataAsDouble(tagList, AQH_MSGDATA_SET_TAGS_DATA, 0.0); } @@ -92,16 +91,16 @@ void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 const char *valueName; const char *valueUnits; int valueType; - char *data; + double data; value=tagList?AQH_IpcdMessageSetData_ReadValue(tagList):NULL; valueName=value?AQH_Value_GetNameForSystem(value):NULL; valueUnits=value?AQH_Value_GetValueUnits(value):NULL; valueType=value?AQH_Value_GetValueType(value):0; - data=tagList?AQH_IpcdMessageSetData_ReadData(tagList):NULL; + data=tagList?AQH_IpcdMessageSetData_ReadData(tagList):0.0; GWEN_Buffer_AppendArgs(dbuf, - "SETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, value=%s)\n", + "SETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, value=%.2f)\n", AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)), sText?sText:"", AQH_IpcMessage_GetCode(msg), @@ -110,8 +109,7 @@ void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 valueName?valueName:"", valueUnits?valueUnits:"", valueType, - data?data:""); - free(data); + data); AQH_Value_free(value); } diff --git a/aqhome/msg/ipc/data/m_ipcd_setdata.h b/aqhome/msg/ipc/data/m_ipcd_setdata.h index 3aee4ba..c6c28d3 100644 --- a/aqhome/msg/ipc/data/m_ipcd_setdata.h +++ b/aqhome/msg/ipc/data/m_ipcd_setdata.h @@ -27,10 +27,10 @@ AQHOME_API AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, - const AQH_VALUE *value, const char *data); + const AQH_VALUE *value, double data); AQHOME_API AQH_VALUE *AQH_IpcdMessageSetData_ReadValue(const GWEN_TAG16_LIST *tagList); -AQHOME_API char *AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList); +AQHOME_API double AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList); AQHOME_API void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, GWEN_BUFFER *dbuf, const char *sText); diff --git a/aqhome/msg/ipc/m_ipc_tag16.c b/aqhome/msg/ipc/m_ipc_tag16.c index a7a2e6d..f151e75 100644 --- a/aqhome/msg/ipc/m_ipc_tag16.c +++ b/aqhome/msg/ipc/m_ipc_tag16.c @@ -161,6 +161,19 @@ uint64_t AQH_Tag16_GetTagDataAsUint64(const GWEN_TAG16_LIST *tagList, unsigned i +double AQH_Tag16_GetTagDataAsDouble(const GWEN_TAG16_LIST *tagList, unsigned int tagType, double defaultValue) +{ + if (tagList) { + const GWEN_TAG16 *tag; + + tag=GWEN_Tag16_List_FindFirstByTagType(tagList, tagType); + return tag?GWEN_Tag16_GetTagDataAsDouble(tag, defaultValue):defaultValue; + } + return defaultValue; +} + + + int AQH_Tag16_WriteValueListAsTagsToBuffer(unsigned int tagType, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *buf) { if (valueList) { diff --git a/aqhome/msg/ipc/m_ipc_tag16.h b/aqhome/msg/ipc/m_ipc_tag16.h index 044169a..1df64b3 100644 --- a/aqhome/msg/ipc/m_ipc_tag16.h +++ b/aqhome/msg/ipc/m_ipc_tag16.h @@ -27,6 +27,7 @@ AQHOME_API GWEN_TAG16_LIST *AQH_Tag16_ParseTags(const uint8_t *payloadPtr, uint3 AQHOME_API char *AQH_Tag16_GetTagDataAsNewString(const GWEN_TAG16_LIST *tagList, unsigned int tagType, const char *defaultValue); AQHOME_API uint32_t AQH_Tag16_GetTagDataAsUint32(const GWEN_TAG16_LIST *tagList, unsigned int tagType, uint32_t defaultValue); AQHOME_API uint64_t AQH_Tag16_GetTagDataAsUint64(const GWEN_TAG16_LIST *tagList, unsigned int tagType, uint64_t defaultValue); +AQHOME_API double AQH_Tag16_GetTagDataAsDouble(const GWEN_TAG16_LIST *tagList, unsigned int tagType, double defaultValue); /* utils */ AQHOME_API int AQH_Tag16_WriteValueListAsTagsToBuffer(unsigned int tagType, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *buf); diff --git a/devices/mqtt/tasmota_plug.xml b/devices/mqtt/tasmota_plug.xml index b6b4e49..cb53d46 100644 --- a/devices/mqtt/tasmota_plug.xml +++ b/devices/mqtt/tasmota_plug.xml @@ -27,8 +27,8 @@ - - + + diff --git a/devices/mqtt/tasmota_plug_old.xml b/devices/mqtt/tasmota_plug_old.xml index 7f7c708..f20d994 100644 --- a/devices/mqtt/tasmota_plug_old.xml +++ b/devices/mqtt/tasmota_plug_old.xml @@ -27,8 +27,8 @@ - - + +