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:
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
94
aqhome/ipc/data/msg_data_connect.c
Normal file
94
aqhome/ipc/data/msg_data_connect.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
50
aqhome/ipc/data/msg_data_connect.h
Normal file
50
aqhome/ipc/data/msg_data_connect.h
Normal 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
|
||||
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user