/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2023 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 #include #include #include #include #include #include #include #define AQH_MSGDATA_VALUES_OFFS_FLAGS 0 /* 4 bytes */ #define AQH_MSGDATA_VALUES_OFFS_NUMVALUES 4 /* 4 bytes */ #define AQH_MSGDATA_VALUES_OFFS_VALUES 8 /* 8 byte */ #define AQH_MSGDATA_VALUES_VALUES_OFFS_ID 0 /* 8 byte */ #define AQH_MSGDATA_VALUES_VALUES_OFFS_NAME 8 /* 104 byte */ # define AQH_MSGDATA_VALUES_VALUES_SIZE_NAME 104 /* 104 byte */ #define AQH_MSGDATA_VALUES_VALUES_OFFS_UNITS 112 /* 16 bytes */ # define AQH_MSGDATA_VALUES_VALUES_SIZE_UNITS 16 #define AQH_MSGDATA_VALUES_VALUES_SIZE 128 #define AQH_MSGDATA_VALUES_MINSIZE (GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_VALUES_OFFS_VALUES) static void _writeValue(const AQH_VALUE *value, uint8_t *ptr, int useSystemName); GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList, int useSystemName) { GWEN_MSG *msg; uint8_t *ptr; int count; int payloadSize; count=valueList?AQH_Value_List_GetCount(valueList):0; payloadSize=AQH_MSGDATA_VALUES_OFFS_VALUES+(count*AQH_MSGDATA_VALUES_VALUES_SIZE); msg=GWEN_IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, payloadSize, NULL); ptr=GWEN_Msg_GetBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD; *(ptr++)=flags & 0xff; *(ptr++)=(flags>>8) & 0xff; *(ptr++)=(flags>>16) & 0xff; *(ptr++)=(flags>>24) & 0xff; *(ptr++)=count & 0xff; *(ptr++)=(count>>8) & 0xff; *(ptr++)=(count>>16) & 0xff; *(ptr++)=(count>>24) & 0xff; if (count>0) { const AQH_VALUE *value; value=AQH_Value_List_First(valueList); while(value) { _writeValue(value, ptr, useSystemName); ptr+=AQH_MSGDATA_VALUES_VALUES_SIZE; value=AQH_Value_List_Next(value); } } return msg; } GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, const AQH_VALUE *value, int useSystemName) { GWEN_MSG *msg; uint8_t *ptr; int count; int payloadSize; count=1; payloadSize=AQH_MSGDATA_VALUES_OFFS_VALUES+AQH_MSGDATA_VALUES_VALUES_SIZE; msg=GWEN_IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, payloadSize, NULL); ptr=GWEN_Msg_GetBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD; *(ptr++)=flags & 0xff; *(ptr++)=(flags>>8) & 0xff; *(ptr++)=(flags>>16) & 0xff; *(ptr++)=(flags>>24) & 0xff; *(ptr++)=count & 0xff; *(ptr++)=(count>>8) & 0xff; *(ptr++)=(count>>16) & 0xff; *(ptr++)=(count>>24) & 0xff; _writeValue(value, ptr, useSystemName); return msg; } void _writeValue(const AQH_VALUE *value, uint8_t *ptr, int useSystemName) { uint64_t i64; const char *name; const char *units; i64=AQH_Value_GetId(value); name=useSystemName?AQH_Value_GetNameForSystem(value):AQH_Value_GetNameForDriver(value); units=AQH_Value_GetValueUnits(value); *(ptr++)=i64 & 0xff; *(ptr++)=(i64>>8) & 0xff; *(ptr++)=(i64>>16) & 0xff; *(ptr++)=(i64>>24) & 0xff; *(ptr++)=(i64>>32) & 0xff; *(ptr++)=(i64>>40) & 0xff; *(ptr++)=(i64>>48) & 0xff; *(ptr++)=(i64>>56) & 0xff; if (name) { strncpy((char*) ptr, name, AQH_MSGDATA_VALUES_VALUES_SIZE_NAME-1); ptr[AQH_MSGDATA_VALUES_VALUES_SIZE_NAME-1]=0; } else memset(ptr, 0, AQH_MSGDATA_VALUES_VALUES_SIZE_NAME); ptr+=AQH_MSGDATA_VALUES_VALUES_SIZE_NAME; if (units) { strncpy((char*) ptr, units, AQH_MSGDATA_VALUES_VALUES_SIZE_UNITS-1); ptr[AQH_MSGDATA_VALUES_VALUES_SIZE_UNITS-1]=0; } else memset(ptr, 0, AQH_MSGDATA_VALUES_VALUES_SIZE_UNITS); ptr+=AQH_MSGDATA_VALUES_VALUES_SIZE_UNITS; } uint32_t AQH_ValuesDataIpcMsg_GetFlags(const GWEN_MSG *msg) { return GWEN_Msg_GetUint32At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_VALUES_OFFS_FLAGS, 0); } uint32_t AQH_ValuesDataIpcMsg_GetNumValues(const GWEN_MSG *msg) { return GWEN_Msg_GetUint32At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_VALUES_OFFS_NUMVALUES, 0); } uint64_t AQH_ValuesDataIpcMsg_GetValueId(const GWEN_MSG *msg, int idx) { uint32_t pos; pos= AQH_MSGDATA_VALUES_OFFS_VALUES+ (idx*AQH_MSGDATA_VALUES_VALUES_SIZE)+ AQH_MSGDATA_VALUES_VALUES_OFFS_ID; return GWEN_Msg_GetUint64At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+pos, 0); } const char *AQH_ValuesDataIpcMsg_GetValueName(const GWEN_MSG *msg, int idx) { uint32_t pos; pos= AQH_MSGDATA_VALUES_OFFS_VALUES+ (idx*AQH_MSGDATA_VALUES_VALUES_SIZE)+ AQH_MSGDATA_VALUES_VALUES_OFFS_NAME; if (GWEN_Msg_GetBytesInBuffer(msg)>=pos+GWEN_MSGIPC_OFFS_PAYLOAD) return (const char*) (GWEN_Msg_GetConstBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD+pos); return NULL; } const char *AQH_ValuesDataIpcMsg_GetValueUnits(const GWEN_MSG *msg, int idx) { uint32_t pos; pos= AQH_MSGDATA_VALUES_OFFS_VALUES+ (idx*AQH_MSGDATA_VALUES_VALUES_SIZE)+ AQH_MSGDATA_VALUES_VALUES_OFFS_UNITS; if (GWEN_Msg_GetBytesInBuffer(msg)>=pos+GWEN_MSGIPC_OFFS_PAYLOAD) return (const char*) (GWEN_Msg_GetConstBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD+pos); return NULL; } int AQH_ValuesDataIpcMsg_IsValid(const GWEN_MSG *msg) { int msgLen; int numValues; const uint8_t *ptr; int i; msgLen=GWEN_Msg_GetBytesInBuffer(msg); if (msgLen=AQH_MSGDATA_VALUES_MINSIZE) { GWEN_Buffer_AppendArgs(dbuf, "VALUES (code=%d, proto=%d, proto version=%d, flags=0x%08x, values=%d)\n", GWEN_IpcMsg_GetCode(msg), GWEN_IpcMsg_GetProtoId(msg), GWEN_IpcMsg_GetProtoVersion(msg), (unsigned int)AQH_ValuesDataIpcMsg_GetFlags(msg), AQH_ValuesDataIpcMsg_GetNumValues(msg)); } }