/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2025 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "aqhome/msg/node/m_value.h" #include "aqhome/msg/node/m_node.h" #include #include #define AQH_MSG_OFFS_VALUE_UID 0 /* 4 bytes */ #define AQH_MSG_OFFS_VALUE_MSGID 4 /* 2 bytes */ #define AQH_MSG_OFFS_VALUE_VALUEID 6 /* 1 byte */ #define AQH_MSG_OFFS_VALUE_VALUETYPE 7 /* 1 byte */ #define AQH_MSG_OFFS_VALUE_VALUE 8 /* 2 bytes */ #define AQH_MSG_OFFS_VALUE_DENOM 10 /* 2 bytes */ AQH_MESSAGE *AQH_ValueMessage_new(uint8_t destAddr, uint8_t srcAddr, uint8_t code, uint16_t msgId, uint8_t valueId, uint16_t value, uint16_t denom) { uint8_t payload[12]; uint8_t *ptr; ptr=payload; *(ptr++)=0; /* uid (empty) */ *(ptr++)=0; *(ptr++)=0; *(ptr++)=0; *(ptr++)=msgId & 0xff; /* msgid */ *(ptr++)=(msgId>>8) & 0xff; *(ptr++)=valueId; /* valueid */ *(ptr++)=0; /* valuetype (empty) */ *(ptr++)=value & 0xff; /* value */ *(ptr++)=(value>>8) & 0xff; *(ptr++)=denom & 0xff; /* denom */ *(ptr++)=(denom>>8) & 0xff; return AQH_NodeMessage_new(destAddr, srcAddr, code, sizeof(payload), payload); } uint32_t AQH_ValueMessage_GetUid(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_UID, 0); } uint16_t AQH_ValueMessage_GetMsgId(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_MSGID, 0); } uint8_t AQH_ValueMessage_GetValueId(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_VALUEID, 0); } uint8_t AQH_ValueMessage_GetValueType(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_VALUETYPE, 0); } uint16_t AQH_ValueMessage_GetValueNom(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_VALUE, 0); } uint16_t AQH_ValueMessage_GetValueDenom(const AQH_MESSAGE *msg) { return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_DENOM, 0); } const char *AQH_ValueMessage_GetValueTypeName(const AQH_MESSAGE *msg) { uint8_t t; t=AQH_ValueMessage_GetValueType(msg); switch(t) { case AQH_MSG_VALUE_TYPE_TEMP: return "temperature"; case AQH_MSG_VALUE_TYPE_HUMIDITY: return "humidity"; case AQH_MSG_VALUE_TYPE_DOOR: return "door_window"; case AQH_MSG_VALUE_TYPE_MOTION: return "motion"; case AQH_MSG_VALUE_TYPE_CO2: return "CO2"; case AQH_MSG_VALUE_TYPE_TVOC: return "TVOC"; default: break; } return "unknown"; } const char *AQH_ValueMessage_GetValueAsWindowStateString(const AQH_MESSAGE *msg) { switch(AQH_ValueMessage_GetValueNom(msg)) { case 0: return "closed"; case 128: return "tilted"; case 255: return "open"; default: break; } return "unknown"; } const char *AQH_ValueMessage_GetValueTypeUnits(const AQH_MESSAGE *msg) { uint8_t t; t=AQH_ValueMessage_GetValueType(msg); switch(t) { case AQH_MSG_VALUE_TYPE_TEMP: return "Celsius"; case AQH_MSG_VALUE_TYPE_HUMIDITY: return "%"; case AQH_MSG_VALUE_TYPE_DOOR: return NULL; case AQH_MSG_VALUE_TYPE_CO2: return "ppm"; case AQH_MSG_VALUE_TYPE_TVOC: return "ppb"; default: break; } return NULL; } double AQH_ValueMessage_GetValue(const AQH_MESSAGE *msg) { double value; double denom; uint16_t intDenom; value=AQH_ValueMessage_GetValueNom(msg); intDenom=AQH_ValueMessage_GetValueDenom(msg); if (intDenom==0) denom=1.0; else denom=(double) intDenom; return (double)(value/denom); } void AQH_ValueMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText) { const char *sCmd; switch(AQH_NodeMessage_GetMsgType(msg)) { case AQH_MSG_TYPE_VALUE_REPORT: sCmd="report"; break; case AQH_MSG_TYPE_VALUE_SET: sCmd="set"; break; case AQH_MSG_TYPE_VALUE_SET_ACK: sCmd="ack"; break; case AQH_MSG_TYPE_VALUE_SET_NACK: sCmd="nack"; break; default: sCmd="unknown"; break; } if (AQH_ValueMessage_GetValueType(msg)==AQH_MSG_VALUE_TYPE_DOOR) GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE(%s) %s (uid=0x%08x, msgId=%u, value_id=0x%02x type=%s value=%s [%04x/%04x])\n", AQH_NodeMessage_GetSourceAddress(msg), AQH_NodeMessage_GetDestAddress(msg), sCmd, sText, (unsigned int) AQH_ValueMessage_GetUid(msg), (unsigned int)AQH_ValueMessage_GetMsgId(msg), AQH_ValueMessage_GetValueId(msg), AQH_ValueMessage_GetValueTypeName(msg), AQH_ValueMessage_GetValueAsWindowStateString(msg), AQH_ValueMessage_GetValueNom(msg), AQH_ValueMessage_GetValueDenom(msg)); else GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE(%s) %s (uid=0x%08x, msgId=%u, value_id=0x%02x type=%s value=%f [%04x/%04x])\n", AQH_NodeMessage_GetSourceAddress(msg), AQH_NodeMessage_GetDestAddress(msg), sCmd, sText, (unsigned int) AQH_ValueMessage_GetUid(msg), (unsigned int)AQH_ValueMessage_GetMsgId(msg), AQH_ValueMessage_GetValueId(msg), AQH_ValueMessage_GetValueTypeName(msg), AQH_ValueMessage_GetValue(msg), AQH_ValueMessage_GetValueNom(msg), AQH_ValueMessage_GetValueDenom(msg)); }