Heavy work on IPC.

We will now have a broker (aqhome-data) which stores data and distributes
value change messages among connected clients.
aqhomed will connect to that broker and send its values there.
aqhome-mqtt will also connect to the broker and send its values there.
Other clients can later connect to check for changes and react according
to rules.
This commit is contained in:
Martin Preuss
2023-09-10 23:13:03 +02:00
parent 2b733a52ca
commit 518a3a53f9
43 changed files with 1412 additions and 707 deletions

View File

@@ -21,6 +21,9 @@
#include <gwenhywfar/json_read.h>
#define AQH_STORAGE_DATAPOINTS_STEPS 128
/* ------------------------------------------------------------------------------------------------
* forward declarations
@@ -219,6 +222,7 @@ void AQH_Storage_AddValue(AQH_STORAGE *sto, AQH_VALUE *value)
id=++(sto->lastValueId);
AQH_Value_SetId(value, id);
AQH_Value_List_Add(value, sto->valueList);
AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED);
}
}
@@ -238,9 +242,9 @@ AQH_VALUE *AQH_Storage_GetValueById(const AQH_STORAGE *sto, uint64_t id)
AQH_VALUE *AQH_Storage_GetValueByName(const AQH_STORAGE *sto, const char *s)
AQH_VALUE *AQH_Storage_GetValueByNameForSystem(const AQH_STORAGE *sto, const char *s)
{
return sto?AQH_Value_List_GetByName(sto->valueList, s):NULL;
return sto?AQH_Value_List_GetByNameForSystem(sto->valueList, s):NULL;
}
@@ -377,6 +381,96 @@ int AQH_Storage_AddDatapoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t timest
uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t fromTime, uint64_t toTime, uint64_t maxArrayLen)
{
AQH_DATAFILE *df;
uint64_t numEntries;
uint64_t arrayLen;
uint64_t arrayPos;
uint64_t *arrayPtr;
uint64_t i;
df=_getDataFileByValueId(sto, valueId);
if (df==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "No file for value id %lu", (unsigned long int) valueId);
return NULL;
}
numEntries=AQH_DataFile_GetNumberOfEntries(df);
if (fromTime==0 && toTime==0)
arrayLen=numEntries+1;
else
arrayLen=AQH_STORAGE_DATAPOINTS_STEPS+1;
if (arrayLen>maxArrayLen+1)
arrayLen=maxArrayLen+1;
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
if (arrayPtr==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen);
free(arrayPtr);
return NULL;
}
arrayPos=1;
for (i=1; i<numEntries; i++) { /* first entry in datafile is reserved */
union {double f; uint64_t i;} u;
uint64_t ts;
int rv;
DBG_INFO(NULL, "Reading record %lu", (unsigned long int) i);
rv=AQH_DataFile_ReadRecord(df, i, &ts, &(u.f));
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
free(arrayPtr);
return NULL;
}
DBG_INFO(NULL, "Read record %lu (%lu - %lf)", (unsigned long int) i, (unsigned long int) ts, u.f);
if ((fromTime==0 || ts>=fromTime) && (toTime==0 || ts<=toTime)) {
DBG_INFO(NULL, "Will add record %lu", (unsigned long int) i);
if (arrayPos>maxArrayLen) {
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
break;
}
if (arrayPos+1>=arrayLen) {
uint64_t newArrayLen;
void *p;
newArrayLen=arrayLen+AQH_STORAGE_DATAPOINTS_STEPS;
if (newArrayLen>maxArrayLen+1)
newArrayLen=maxArrayLen+1;
if (newArrayLen==arrayLen) {
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
break;
}
p=realloc((void*) arrayPtr, newArrayLen*sizeof(uint64_t));
if (p==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen+AQH_STORAGE_DATAPOINTS_STEPS);
free(arrayPtr);
return NULL;
}
arrayPtr=(uint64_t*) p;
arrayLen=newArrayLen;
}
arrayPtr[arrayPos++]=ts;
arrayPtr[arrayPos++]=u.i;
}
else {
DBG_INFO(NULL, "Entry %lu does not match", (unsigned long int) i);
}
} /* for */
if (arrayPos<=1) {
DBG_INFO(AQH_LOGDOMAIN, "No matching records");
free(arrayPtr);
return NULL;
}
arrayPtr[0]=arrayPos-1;
return arrayPtr;
}
void AQH_Storage_HandleMqttPublish(AQH_STORAGE *sto, const char *sTopic, const char *sValue)
{
if (sto) {
@@ -470,7 +564,7 @@ void _handleValueForJsonElement(AQH_STORAGE *sto,
}
}
else {
DBG_INFO(AQH_LOGDOMAIN, "No datapath in value \"%s\"", AQH_Value_GetName(value));
DBG_INFO(AQH_LOGDOMAIN, "No datapath in value \"%s\"", AQH_Value_GetNameForSystem(value));
}
}

View File

@@ -67,7 +67,7 @@ AQHOME_API AQH_MQTT_TOPIC *AQH_Storage_GetMqttTopicByTopic(const AQH_STORAGE *st
AQHOME_API void AQH_Storage_AddValue(AQH_STORAGE *sto, AQH_VALUE *value);
AQHOME_API AQH_VALUE_LIST *AQH_Storage_GetValueList(const AQH_STORAGE *sto);
AQHOME_API AQH_VALUE *AQH_Storage_GetValueById(const AQH_STORAGE *sto, uint64_t id);
AQHOME_API AQH_VALUE *AQH_Storage_GetValueByName(const AQH_STORAGE *sto, const char *s);
AQHOME_API AQH_VALUE *AQH_Storage_GetValueByNameForSystem(const AQH_STORAGE *sto, const char *s);
AQHOME_API const char *AQH_Storage_GetStateFile(const AQH_STORAGE *sto);
AQHOME_API void AQH_Storage_SetStateFile(AQH_STORAGE *sto, const char *s);
@@ -87,6 +87,9 @@ AQHOME_API int AQH_Storage_Fini(AQH_STORAGE *sto);
AQHOME_API int AQH_Storage_WriteState(AQH_STORAGE *sto);
AQHOME_API int AQH_Storage_AddDatapoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t timestamp, double dataPoint);
AQHOME_API uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId,
uint64_t fromTime, uint64_t toTime,
uint64_t maxArrayLen);
AQHOME_API void AQH_Storage_HandleMqttPublish(AQH_STORAGE *sto, const char *topic, const char *value);

View File

@@ -49,7 +49,21 @@
<flags>with_getbymember</flags>
</member>
<member name="name" type="char_ptr" maxlen="32">
<member name="driver" type="char_ptr" maxlen="32">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="nameForDriver" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="nameForSystem" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>

View File

@@ -48,6 +48,7 @@
endpoint_ipc.h
msg_ipc_result.h
msg_ipc_qwords.h
msg_ipc_tag16.h
</headers>
@@ -62,6 +63,7 @@
endpoint_ipc.c
msg_ipc_result.c
msg_ipc_qwords.c
msg_ipc_tag16.c
</sources>

View File

@@ -46,10 +46,9 @@
<headers dist="true" install="$(pkgincludedir)/ipc" >
ipc_data.h
msg_data_getvalues_rsp.c
msg_data_getvalues_rsp.h
msg_data_values.h
msg_data_datapoints.h
msg_data_connect.h
</headers>
@@ -61,10 +60,9 @@
$(local/typefiles)
ipc_data.c
msg_data_getvalues_req.c
msg_data_getvalues_rsp.c
msg_data_values.c
msg_data_datapoints.c
msg_data_connect.c
</sources>

View File

@@ -21,23 +21,40 @@
#define AQH_MSGTYPE_IPC_DATA_RESULT 0x001 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ 0x100 /* AQH_QwordsIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0x200 /* AQH_ValuesDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_CONNECT_REQ 0x010 /* serviceName, userName, password */
#define AQH_MSGTYPE_IPC_DATA_ADDVALUES_REQ 0x300 /* AQH_ValuesDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_ADDVALUES_RSP 0x400 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_UPDATEDATA 0x100 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_DATACHANGED 0x200 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_EDITVALUE_REQ 0x500 /* AQH_ValuesDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_EDITVALUE_RSP 0x600 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_SETDATA_REQ 0x300 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_SETDATA_RSP 0x400 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_ADDDATAPOINTS_REQ 0x700 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_ADDDATAPOINTS_RSP 0x800 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETDATA_REQ 0x500 /* AQH_DataPointsDataIpcMsg (1 pair: fromTime, toTime) */
#define AQH_MSGTYPE_IPC_DATA_GETDATA_RSP 0x600 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETDATAPOINTS_REQ 0x900 /* AQH_DataPointsDataIpcMsg (1 pair: fromTime, toTime) */
#define AQH_MSGTYPE_IPC_DATA_GETDATAPOINTS_RSP 0xa00 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ 0x700 /* AQH_DataPointsDataIpcMsg (0 datapoints) */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_RSP 0x800 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATAPOINT_REQ 0xb00 /* AQH_DataPointsDataIpcMsg (0 datapoints) */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATAPOINT_RSP 0xc00 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ 0x900 /* AQH_QwordsIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0xa00 /* AQH_ValuesDataIpcMsg */
/* remove */
#define AQH_MSGTYPE_IPC_DATA_ADDVALUES_REQ 0xf01 /* AQH_ValuesDataIpcMsg -> remove */
#define AQH_MSGTYPE_IPC_DATA_ADDVALUES_RSP 0xf02 /* AQH_ResultIpcMsg -> remove */
#define AQH_MSGTYPE_IPC_DATA_EDITVALUE_REQ 0xf03 /* AQH_ValuesDataIpcMsg -> remove */
#define AQH_MSGTYPE_IPC_DATA_EDITVALUE_RSP 0xf04 /* AQH_ResultIpcMsg -> remove */
#define AQH_MSGTYPE_IPC_DATA_ADDDATAPOINTS_REQ 0xf05 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_ADDDATAPOINTS_RSP 0xf06 /* AQH_ResultIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETDATAPOINTS_REQ 0xf07 /* AQH_DataPointsDataIpcMsg (1 pair: fromTime, toTime) */
#define AQH_MSGTYPE_IPC_DATA_GETDATAPOINTS_RSP 0xf08 /* AQH_DataPointsDataIpcMsg */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATAPOINT_REQ 0xf09 /* AQH_DataPointsDataIpcMsg (0 datapoints) */
#define AQH_MSGTYPE_IPC_DATA_GETLASTDATAPOINT_RSP 0xf0a /* AQH_DataPointsDataIpcMsg */

View File

@@ -0,0 +1,94 @@
/****************************************************************************
* 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 <config.h>
#endif
#include <aqhome/ipc/data/msg_data_connect.h>
#include <aqhome/ipc/data/ipc_data.h>
#include <aqhome/ipc/msg_ipc_tag16.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/msg_ipc.h>
#define AQH_MSGDATA_CONNECT_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD
GWEN_MSG *AQH_ConnectDataIpcMsg_new(uint16_t code, const char *clientId, const char *userId, const char *password, uint32_t flags)
{
GWEN_MSG *msg;
GWEN_BUFFER *buf;
buf=GWEN_Buffer_new(0, 256, 0, 1);
if (clientId && *clientId)
GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_CONNECT_TAGS_CLIENTID, clientId, buf);
if (userId && *userId)
GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_CONNECT_TAGS_USERID, userId, buf);
if (password && *password)
GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_CONNECT_TAGS_PASSWORD, password, buf);
GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_CONNECT_TAGS_FLAGS, flags, buf);
msg=AQH_Tag16IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code,
GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
GWEN_Buffer_free(buf);
return msg;
}
void AQH_ConnectDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_CONNECT_MINSIZE) {
GWEN_TAG16_LIST *tagList;
char *clientId=NULL;
char *userId=NULL;
uint32_t flags=0;
tagList=AQH_Tag16IpcMsg_ParseTags(msg, 0);
if (tagList) {
const GWEN_TAG16 *tag;
tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_CONNECT_TAGS_CLIENTID);
clientId=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_CONNECT_TAGS_USERID);
userId=tag?GWEN_Tag16_GetTagDataAsNewString(tag, NULL):NULL;
tag=GWEN_Tag16_List_FindFirstByTagType(tagList, AQH_MSGDATA_CONNECT_TAGS_FLAGS);
flags=tag?GWEN_Tag16_GetTagDataAsUint32(tag, 0):0;
}
GWEN_Buffer_AppendArgs(dbuf,
"CONNECT (code=%d, proto=%d, proto version=%d, clientId=%s, userId=%s, flags=%08x)\n",
GWEN_IpcMsg_GetCode(msg),
GWEN_IpcMsg_GetProtoId(msg),
GWEN_IpcMsg_GetProtoVersion(msg),
clientId?clientId:"<empty>",
userId?userId:"<empty>",
flags);
free(userId);
free(clientId);
GWEN_Tag16_List_free(tagList);
}
}

View File

@@ -0,0 +1,50 @@
/****************************************************************************
* 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.
****************************************************************************/
#ifndef AQH_MSG_IPC_DATA_CONNECT_H
#define AQH_MSG_IPC_DATA_CONNECT_H
#include <aqhome/api.h>
#include <aqhome/data/value.h>
#include <gwenhywfar/msg_ipc.h>
/**
* This message is used in request AQH_MSGTYPE_IPC_DATA_ADDVALUES_REQ and in response AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP.
*/
#define AQH_MSGDATA_CONNECT_TAGS_CLIENTID 0x0001
#define AQH_MSGDATA_CONNECT_TAGS_USERID 0x0002
#define AQH_MSGDATA_CONNECT_TAGS_PASSWORD 0x0003
#define AQH_MSGDATA_CONNECT_TAGS_FLAGS 0x0004
#define AQH_MSGDATA_CONNECT_FLAGS_WANTUPDATES 0x0001
AQHOME_API GWEN_MSG *AQH_ConnectDataIpcMsg_new(uint16_t code,
const char *clientId,
const char *userId, const char *password,
uint32_t flags);
AQHOME_API int AQH_ConnectDataIpcMsg_IsValid(const GWEN_MSG *msg);
AQHOME_API void AQH_ConnectDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

View File

@@ -1,52 +0,0 @@
/****************************************************************************
* 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 <config.h>
#endif
#include <aqhome/ipc/data/msg_data_getvalues_req.h>
#include <aqhome/ipc/data/ipc_data.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/msg_ipc.h>
GWEN_MSG *AQH_GetValuesReqDataIpcMsg_new(uint16_t code)
{
return GWEN_IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, 0, NULL);
}
void AQH_GetValuesReqDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if (GWEN_Msg_GetBytesInBuffer(msg)>=GWEN_MSGIPC_OFFS_PAYLOAD) {
GWEN_Buffer_AppendArgs(dbuf,
"GETVALUESREQ (code=%d, proto=%d, proto version=%d)\n",
GWEN_IpcMsg_GetCode(msg),
GWEN_IpcMsg_GetProtoId(msg),
GWEN_IpcMsg_GetProtoVersion(msg));
}
}

View File

@@ -1,28 +0,0 @@
/****************************************************************************
* 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.
****************************************************************************/
#ifndef AQH_MSG_IPC_DATA_GETVALUES_REQ_H
#define AQH_MSG_IPC_DATA_GETVALUES_REQ_H
#include <aqhome/api.h>
#include <gwenhywfar/msg_ipc.h>
AQHOME_API GWEN_MSG *AQH_GetValuesReqDataIpcMsg_new(uint16_t code);
#endif

View File

@@ -1,210 +0,0 @@
/****************************************************************************
* 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 <config.h>
#endif
#include <aqhome/ipc/data/msg_data_getvalues_rsp.h>
#include <aqhome/ipc/data/ipc_data.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/msg_ipc.h>
#include <string.h>
#define AQH_MSGDATA_GETVALUES_RSP_OFFS_FLAGS 0 /* 4 bytes */
#define AQH_MSGDATA_GETVALUES_RSP_OFFS_NUMVALUES 4 /* 4 bytes */
#define AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES 8 /* 8 byte */
#define AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_ID 0 /* 8 byte */
#define AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_NAME 8 /* 104 byte */
# define AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_NAME 104 /* 104 byte */
#define AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_UNITS 112 /* 16 bytes */
# define AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS 16
#define AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE 128
#define AQH_MSGDATA_GETVALUES_RSP_MINSIZE (GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES)
GWEN_MSG *AQH_GetValuesRspDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList)
{
GWEN_MSG *msg;
uint8_t *ptr;
int count;
int payloadSize;
count=AQH_Value_List_GetCount(valueList);
payloadSize=AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES+(count*AQH_MSGDATA_GETVALUES_RSP_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) {
uint64_t i64;
const char *name;
const char *units;
i64=AQH_Value_GetId(value);
name=AQH_Value_GetName(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_GETVALUES_RSP_VALUES_SIZE_NAME-1);
ptr[AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_NAME-1]=0;
}
else
memset(ptr, 0, AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_NAME);
ptr+=AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_NAME;
if (units) {
strncpy((char*) ptr, units, AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS-1);
ptr[AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS-1]=0;
}
else
memset(ptr, 0, AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS);
ptr+=AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS;
value=AQH_Value_List_Next(value);
}
}
return msg;
}
uint32_t AQH_GetValuesRspDataIpcMsg_GetFlags(const GWEN_MSG *msg)
{
return GWEN_Msg_GetUint32At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_GETVALUES_RSP_OFFS_FLAGS, 0);
}
uint32_t AQH_GetValuesRspDataIpcMsg_GetNumValues(const GWEN_MSG *msg)
{
return GWEN_Msg_GetUint32At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_GETVALUES_RSP_OFFS_NUMVALUES, 0);
}
uint8_t AQH_GetValuesRspDataIpcMsg_GetValueId(const GWEN_MSG *msg, int idx)
{
uint32_t pos;
pos=
AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES+
(idx*AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE)+
AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_ID;
return GWEN_Msg_GetUint64At(msg, GWEN_MSGIPC_OFFS_PAYLOAD+pos, 0);
}
const char *AQH_GetValuesRspDataIpcMsg_GetValueName(const GWEN_MSG *msg, int idx)
{
uint32_t pos;
pos=
AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES+
(idx*AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE)+
AQH_MSGDATA_GETVALUES_RSP_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;
}
int AQH_GetValuesRspDataIpcMsg_IsValid(const GWEN_MSG *msg)
{
int msgLen;
int numValues;
const uint8_t *ptr;
int i;
msgLen=GWEN_Msg_GetBytesInBuffer(msg);
if (msgLen<AQH_MSGDATA_GETVALUES_RSP_MINSIZE) {
DBG_ERROR(AQH_LOGDOMAIN, "Message too small (%d<%d)", GWEN_Msg_GetBytesInBuffer(msg), AQH_MSGDATA_GETVALUES_RSP_MINSIZE);
return 0;
}
numValues=(int)AQH_GetValuesRspDataIpcMsg_GetNumValues(msg);
if (msgLen<(numValues*AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE)+AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES+GWEN_MSGIPC_OFFS_PAYLOAD) {
DBG_ERROR(AQH_LOGDOMAIN, "Message too small to contain %d values", numValues);
return 0;
}
ptr=GWEN_Msg_GetConstBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD+AQH_MSGDATA_GETVALUES_RSP_OFFS_VALUES;
for (i=0; i<numValues; i++) {
if (ptr[AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_NAME+AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_NAME-1]!=0) {
DBG_ERROR(AQH_LOGDOMAIN, "Name string for value %d is not null-terminated", i);
return 0;
}
if (ptr[AQH_MSGDATA_GETVALUES_RSP_VALUES_OFFS_UNITS+AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE_UNITS-1]!=0) {
DBG_ERROR(AQH_LOGDOMAIN, "Units string for value %d is not null-terminated", i);
return 0;
}
ptr+=AQH_MSGDATA_GETVALUES_RSP_VALUES_SIZE;
}
return 1;
}
void AQH_GetValuesRspDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_GETVALUES_RSP_MINSIZE) {
GWEN_Buffer_AppendArgs(dbuf,
"GETVALUESRSP (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_GetValuesRspDataIpcMsg_GetFlags(msg),
AQH_GetValuesRspDataIpcMsg_GetNumValues(msg));
}
}

View File

@@ -1,42 +0,0 @@
/****************************************************************************
* 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.
****************************************************************************/
#ifndef AQH_MSG_IPC_DATA_GETVALUES_RSP_H
#define AQH_MSG_IPC_DATA_GETVALUES_RSP_H
#include <aqhome/api.h>
#include <aqhome/data/value.h>
#include <gwenhywfar/msg_ipc.h>
#define AQH_MSGDATA_GETVALUES_RSP_FLAGS_LASTMSG 0x0001
AQHOME_API GWEN_MSG *AQH_GetValuesRspDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList);
AQHOME_API uint32_t AQH_GetValuesRspDataIpcMsg_GetFlags(const GWEN_MSG *msg);
AQHOME_API uint32_t AQH_GetValuesRspDataIpcMsg_GetNumValues(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_GetValuesRspDataIpcMsg_GetValueId(const GWEN_MSG *msg, int idx);
AQHOME_API const char *AQH_GetValuesRspDataIpcMsg_GetValueName(const GWEN_MSG *msg, int idx);
AQHOME_API int AQH_GetValuesRspDataIpcMsg_IsValid(const GWEN_MSG *msg);
AQHOME_API void AQH_GetValuesRspDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

View File

@@ -42,12 +42,12 @@
static void _writeValue(const AQH_VALUE *value, uint8_t *ptr);
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)
GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList, int useSystemName)
{
GWEN_MSG *msg;
uint8_t *ptr;
@@ -74,7 +74,7 @@ GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALU
value=AQH_Value_List_First(valueList);
while(value) {
_writeValue(value, ptr);
_writeValue(value, ptr, useSystemName);
ptr+=AQH_MSGDATA_VALUES_VALUES_SIZE;
value=AQH_Value_List_Next(value);
}
@@ -84,7 +84,7 @@ GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALU
GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, const AQH_VALUE *value)
GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, const AQH_VALUE *value, int useSystemName)
{
GWEN_MSG *msg;
uint8_t *ptr;
@@ -106,21 +106,21 @@ GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, con
*(ptr++)=(count>>16) & 0xff;
*(ptr++)=(count>>24) & 0xff;
_writeValue(value, ptr);
_writeValue(value, ptr, useSystemName);
return msg;
}
void _writeValue(const AQH_VALUE *value, uint8_t *ptr)
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=AQH_Value_GetName(value);
name=useSystemName?AQH_Value_GetNameForSystem(value):AQH_Value_GetNameForDriver(value);
units=AQH_Value_GetValueUnits(value);
*(ptr++)=i64 & 0xff;

View File

@@ -24,8 +24,8 @@
#define AQH_MSGDATA_VALUES_FLAGS_LASTMSG 0x0001
AQHOME_API GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList);
AQHOME_API GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, const AQH_VALUE *value);
AQHOME_API GWEN_MSG *AQH_ValuesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_VALUE_LIST *valueList, int useSystemName);
AQHOME_API GWEN_MSG *AQH_ValuesDataIpcMsg_newForOneValue(uint16_t code, uint32_t flags, const AQH_VALUE *value, int useSystemName);
AQHOME_API uint32_t AQH_ValuesDataIpcMsg_GetFlags(const GWEN_MSG *msg);

View File

@@ -55,6 +55,10 @@ void _freeData(void *bp, void *p)
AQH_ENDPOINT_IPC *xep;
xep=(AQH_ENDPOINT_IPC*) p;
free(xep->serviceName);
free(xep->userName);
GWEN_FREE_OBJECT(xep);
}
@@ -115,6 +119,94 @@ void AQH_IpcEndpoint_SubAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t i)
const char *AQH_IpcEndpoint_GetServiceName(const GWEN_MSG_ENDPOINT *ep)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep)
return xep->serviceName;
}
return NULL;
}
void AQH_IpcEndpoint_SetServiceName(GWEN_MSG_ENDPOINT *ep, const char *s)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep) {
free(xep->serviceName);
xep->serviceName=s?strdup(s):NULL;
}
}
}
const char *AQH_IpcEndpoint_GetUserName(const GWEN_MSG_ENDPOINT *ep)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep)
return xep->userName;
}
return NULL;
}
void AQH_IpcEndpoint_SetUserName(GWEN_MSG_ENDPOINT *ep, const char *s)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep) {
free(xep->userName);
xep->userName=s?strdup(s):NULL;
}
}
}
uint32_t AQH_IpcEndpoint_GetPermissions(const GWEN_MSG_ENDPOINT *ep)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep)
return xep->permissions;
}
return 0;
}
void AQH_IpcEndpoint_SetPermissions(GWEN_MSG_ENDPOINT *ep, uint32_t i)
{
if (ep) {
AQH_ENDPOINT_IPC *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_IPC, ep);
if (xep)
xep->permissions=i;
}
}
GWEN_MSG_ENDPOINT *AQH_IpcEndpoint_CreateIpcTcpClient(const char *host, int port, const char *name, int groupId)
{
GWEN_MSG_ENDPOINT *ep;

View File

@@ -15,6 +15,17 @@
#include <gwenhywfar/endpoint.h>
#define AQH_IPCENDPOINT_FLAGS_WANTUPDATES 0x0001
#define AQH_IPCENDPOINT_PERMS_LISTVALUES 0x0001
#define AQH_IPCENDPOINT_PERMS_READVALUE 0x0002
#define AQH_IPCENDPOINT_PERMS_ADDVALUE 0x0004
#define AQH_IPCENDPOINT_PERMS_LISTDATA 0x0010
#define AQH_IPCENDPOINT_PERMS_READDATA 0x0020
#define AQH_IPCENDPOINT_PERMS_ADDDATA 0x0040
AQHOME_API void AQH_IpcEndpoint_Extend(GWEN_MSG_ENDPOINT *ep);
@@ -26,6 +37,15 @@ AQHOME_API void AQH_IpcEndpoint_SetAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint
AQHOME_API void AQH_IpcEndpoint_AddAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t i);
AQHOME_API void AQH_IpcEndpoint_SubAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t i);
AQHOME_API const char *AQH_IpcEndpoint_GetServiceName(const GWEN_MSG_ENDPOINT *ep);
AQHOME_API void AQH_IpcEndpoint_SetServiceName(GWEN_MSG_ENDPOINT *ep, const char *s);
AQHOME_API const char *AQH_IpcEndpoint_GetUserName(const GWEN_MSG_ENDPOINT *ep);
AQHOME_API void AQH_IpcEndpoint_SetUserName(GWEN_MSG_ENDPOINT *ep, const char *s);
AQHOME_API uint32_t AQH_IpcEndpoint_GetPermissions(const GWEN_MSG_ENDPOINT *ep);
AQHOME_API void AQH_IpcEndpoint_SetPermissions(GWEN_MSG_ENDPOINT *ep, uint32_t i);
#endif

View File

@@ -20,6 +20,9 @@
typedef struct AQH_ENDPOINT_IPC AQH_ENDPOINT_IPC;
struct AQH_ENDPOINT_IPC {
uint32_t acceptedMsgGroups;
char *serviceName;
char *userName;
uint32_t permissions;
};

View File

@@ -22,12 +22,14 @@
#define AQH_IPC_PROTOCOL_RESULT_VERSION 1
#define AQH_MSG_IPC_SUCCESS 0
#define AQH_MSG_IPC_ERROR_GENERIC 1
#define AQH_MSG_IPC_ERROR_INVALID 2
#define AQH_MSG_IPC_ERROR_EXISTS 3
#define AQH_MSG_IPC_ERROR_NODATA 4
#define AQH_MSG_IPC_ERROR_BADDATA 5
#define AQH_MSG_IPC_SUCCESS 0
#define AQH_MSG_IPC_ERROR_GENERIC 1
#define AQH_MSG_IPC_ERROR_INVALID 2
#define AQH_MSG_IPC_ERROR_EXISTS 3
#define AQH_MSG_IPC_ERROR_NODATA 4
#define AQH_MSG_IPC_ERROR_BADDATA 5
#define AQH_MSG_IPC_ERROR_PERMS 6
#define AQH_MSG_IPC_ERROR_NOTFOUND 7
AQHOME_API GWEN_MSG *AQH_ResultIpcMsg_new(uint16_t code, uint32_t resultCode);

View File

@@ -18,25 +18,9 @@
GWEN_MSG *AQH_Tag16IpcMsg_new(uint8_t protoId, uint8_t protoVer, uint16_t code, const GWEN_TAG16_LIST *tagList)
GWEN_MSG *AQH_Tag16IpcMsg_new(uint8_t protoId, uint8_t protoVer, uint16_t code, uint32_t payloadLen, const uint8_t *payload)
{
GWEN_MSG *msg;
const GWEN_TAG16 *tag;
GWEN_BUFFER *buf;
buf=GWEN_Buffer_new(0, 256, 0, 1);
tag=GWEN_Tag16_List_First(tagList);
while(tag) {
GWEN_Tag16_DirectlyToBuffer(GWEN_Tag16_GetTagType(tag),
GWEN_Tag16_GetTagData(tag),
GWEN_Tag16_GetTagLength(tag),
buf);
tag=GWEN_Tag16_List_Next(tag);
}
msg=GWEN_IpcMsg_new(protoId, protoVer, code, GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
GWEN_Buffer_free(buf);
return msg;
return GWEN_IpcMsg_new(protoId, protoVer, code, payloadLen, payload);
}
@@ -49,33 +33,20 @@ GWEN_TAG16_LIST *AQH_Tag16IpcMsg_ParseTags(const GWEN_MSG *msg, int doCopy)
if (msgSize>GWEN_MSGIPC_OFFS_PAYLOAD) {
const uint8_t *ptr;
uint32_t payloadSize;
GWEN_TAG16_LIST *tagList;
ptr=GWEN_Msg_GetConstBuffer(msg)+GWEN_MSGIPC_OFFS_PAYLOAD;
payloadSize=msgSize-GWEN_MSGIPC_OFFS_PAYLOAD;
tagList=GWEN_Tag16_List_new();
while(payloadSize) {
GWEN_TAG16 *tag;
unsigned int tagSize;
tag=GWEN_Tag16_fromBuffer2(ptr, payloadSize, doCopy);
if (tag==NULL)
break;
tagSize=GWEN_Tag16_GetTagSize(tag);
if (payloadSize>tagSize) {
DBG_ERROR(AQH_LOGDOMAIN, "Error in tag size");
GWEN_Tag16_List_free(tagList);
if (payloadSize) {
GWEN_TAG16_LIST *tagList;
tagList=GWEN_Tag16_List_fromBuffer(ptr, payloadSize, doCopy);
if (tagList==NULL) {
DBG_INFO(AQH_LOGDOMAIN, "Error reading tags from message");
return NULL;
}
GWEN_Tag16_List_Add(tag, tagList);
ptr+=tagSize;
payloadSize-=tagSize;
} /* while */
if (GWEN_Tag16_List_GetCount(tagList)<1) {
GWEN_Tag16_List_free(tagList);
return NULL;
return tagList;
}
return tagList;
}
return NULL;

View File

@@ -17,7 +17,7 @@
#include <gwenhywfar/tag16.h>
AQHOME_API GWEN_MSG *AQH_Tag16IpcMsg_new(uint8_t protoId, uint8_t protoVer, uint16_t code, const GWEN_TAG16_LIST *tagList);
AQHOME_API GWEN_MSG *AQH_Tag16IpcMsg_new(uint8_t protoId, uint8_t protoVer, uint16_t code, uint32_t payloadLen, const uint8_t *payload);
AQHOME_API GWEN_TAG16_LIST *AQH_Tag16IpcMsg_ParseTags(const GWEN_MSG *msg, int doCopy);
AQHOME_API void AQH_Tag16IpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);