From 45da38b64a622299aa14cdb7bb569ebfb315e091 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sun, 1 Oct 2023 23:44:26 +0200 Subject: [PATCH] added devices, added command getdevices. --- apps/aqhome-data/0BUILD | 2 + apps/aqhome-data/c_connect.c | 6 +- apps/aqhome-data/c_getdevices.c | 104 +++++++ apps/aqhome-data/c_getdevices.h | 25 ++ apps/aqhome-data/init.c | 2 +- apps/aqhome-data/loop.c | 74 ++++- apps/aqhome-tool/data/0BUILD | 2 + apps/aqhome-tool/data/getdevices.c | 239 ++++++++++++++++ apps/aqhome-tool/{nodes => data}/getdevices.h | 3 +- apps/aqhome-tool/main.c | 6 +- apps/aqhome-tool/nodes/0BUILD | 4 +- .../nodes/{getdevices.c => getnodes.c} | 10 +- apps/aqhome-tool/nodes/getnodes.h | 20 ++ aqhome/data/0BUILD | 4 + aqhome/data/device.t2d | 14 + aqhome/data/storage.c | 40 +++ aqhome/data/storage.h | 7 +- aqhome/data/storage_p.h | 11 +- aqhome/data/storage_readxml.c | 26 ++ aqhome/data/storage_writexml.c | 26 +- aqhome/ipc/data/0BUILD | 2 + aqhome/ipc/data/ipc_data.c | 257 +++++++++++++++++- aqhome/ipc/data/ipc_data.h | 21 +- aqhome/ipc/data/msg_data_devices.c | 150 ++++++++++ aqhome/ipc/data/msg_data_devices.h | 52 ++++ aqhome/ipc/endpoint_ipc.h | 19 +- 26 files changed, 1076 insertions(+), 50 deletions(-) create mode 100644 apps/aqhome-data/c_getdevices.c create mode 100644 apps/aqhome-data/c_getdevices.h create mode 100644 apps/aqhome-tool/data/getdevices.c rename apps/aqhome-tool/{nodes => data}/getdevices.h (86%) rename apps/aqhome-tool/nodes/{getdevices.c => getnodes.c} (96%) create mode 100644 apps/aqhome-tool/nodes/getnodes.h create mode 100644 aqhome/ipc/data/msg_data_devices.c create mode 100644 aqhome/ipc/data/msg_data_devices.h diff --git a/apps/aqhome-data/0BUILD b/apps/aqhome-data/0BUILD index 46d9adf..1eeccd4 100644 --- a/apps/aqhome-data/0BUILD +++ b/apps/aqhome-data/0BUILD @@ -43,6 +43,7 @@ c_connect.h c_updatedata.h c_getvalues.h + c_getdevices.h c_getdatapoints.h c_getlastdatapoint.h c_setdata.h @@ -59,6 +60,7 @@ c_connect.c c_updatedata.c c_getvalues.c + c_getdevices.c c_getdatapoints.c c_getlastdatapoint.c c_setdata.c diff --git a/apps/aqhome-data/c_connect.c b/apps/aqhome-data/c_connect.c index 3b0c629..0eafa27 100644 --- a/apps/aqhome-data/c_connect.c +++ b/apps/aqhome-data/c_connect.c @@ -74,7 +74,11 @@ void AqHomeData_HandleConnect(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG AQH_IPCENDPOINT_PERMS_ADDVALUE | AQH_IPCENDPOINT_PERMS_LISTDATA | AQH_IPCENDPOINT_PERMS_READDATA | - AQH_IPCENDPOINT_PERMS_ADDDATA); + AQH_IPCENDPOINT_PERMS_ADDDATA | + AQH_IPCENDPOINT_PERMS_LISTDEVICES | + AQH_IPCENDPOINT_PERMS_READDEVICE | + AQH_IPCENDPOINT_PERMS_ADDDEVICE | + AQH_IPCENDPOINT_PERMS_MODDEVICE); free(passw); free(userId); free(clientId); diff --git a/apps/aqhome-data/c_getdevices.c b/apps/aqhome-data/c_getdevices.c new file mode 100644 index 0000000..af192af --- /dev/null +++ b/apps/aqhome-data/c_getdevices.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * 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 "./c_getdevices.h" +#include "./aqhome_data_p.h" +#include "aqhome/ipc/data/ipc_data.h" +#include "aqhome/ipc/data/msg_data_devices.h" +#include "aqhome/ipc/msg_ipc_result.h" + +#include + + + +/* ------------------------------------------------------------------------------------------------ + * defines + * ------------------------------------------------------------------------------------------------ + */ + +#define AQHOMEDATA_DEVICESPERMSG 10 + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _sendDeviceList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +void AqHomeData_HandleGetDevices(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg) +{ + const AQH_DEVICE_LIST *origDeviceList; + + DBG_INFO(NULL, "HandleGetDevices"); + origDeviceList=AQH_Storage_GetDeviceList(aqh->storage); + if (origDeviceList) { + DBG_INFO(NULL, "Have a list of %d devices", AQH_Device_List_GetCount(origDeviceList)); + if (AQH_Device_List_GetCount(origDeviceList)=AQHOMEDATA_DEVICESPERMSG) { + DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList)); + _sendDeviceList(aqh, ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG); + AQH_Device_List_Clear(tmpDeviceList); + } + v=next; + } + if (AQH_Device_List_GetCount(tmpDeviceList)) { + DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList)); + _sendDeviceList(aqh, ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG); /* send remaining */ + } + AQH_Device_List_free(tmpDeviceList); + } + } + else { + /* empty list */ + _sendDeviceList(aqh, ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG); + } +} + + + +void _sendDeviceList(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags) +{ + GWEN_MSG *msg; + + msg=AQH_DevicesDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP, flags, vl); + GWEN_MsgEndpoint_AddSendMessage(ep, msg); +} + + + diff --git a/apps/aqhome-data/c_getdevices.h b/apps/aqhome-data/c_getdevices.h new file mode 100644 index 0000000..5d1dc01 --- /dev/null +++ b/apps/aqhome-data/c_getdevices.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * 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 AQHOME_DATA_C_GETDEVICES_H +#define AQHOME_DATA_C_GETDEVICES_H + + +#include "./aqhome_data.h" + + +void AqHomeData_HandleGetDevices(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg); + + + +#endif + + + + + diff --git a/apps/aqhome-data/init.c b/apps/aqhome-data/init.c index c2b717b..36d294b 100644 --- a/apps/aqhome-data/init.c +++ b/apps/aqhome-data/init.c @@ -45,7 +45,7 @@ * ------------------------------------------------------------------------------------------------ */ -//#define I18N(msg) msg +#define I18N(msg) msg #define I18S(msg) msg diff --git a/apps/aqhome-data/loop.c b/apps/aqhome-data/loop.c index 7e4d345..64db4a3 100644 --- a/apps/aqhome-data/loop.c +++ b/apps/aqhome-data/loop.c @@ -17,6 +17,7 @@ #include "./c_getdatapoints.h" #include "./c_getlastdatapoint.h" #include "./c_getvalues.h" +#include "./c_getdevices.h" #include "./c_setdata.h" #include "./c_addvalue.h" #include "./aqhome_data_p.h" @@ -49,6 +50,7 @@ static void _readAndHandleIpcMessages(AQHOME_DATA *aqh); static void _handleIpcEndpoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep); static void _handleIpcMsg(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg); +static AQH_DEVICE *_getOrCreateDeviceForDriver(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epDriver, const char *nameForDriver); @@ -144,9 +146,11 @@ AQH_VALUE *AqHomeData_GetOrCreateValueForDriverWithTemplate(AQHOME_DATA *aqh, AQH_VALUE *v; GWEN_BUFFER *buf; const char *nameForDriver; + const char *deviceNameForDriver; serviceName=AQH_IpcEndpoint_GetServiceName(epDriver); nameForDriver=AQH_Value_GetNameForDriver(valueTemplate); + deviceNameForDriver=AQH_Value_GetDeviceNameForDriver(valueTemplate); buf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendArgs(buf, "%s/%s", (serviceName && *serviceName)?serviceName:"unknown", nameForDriver); @@ -154,8 +158,11 @@ AQH_VALUE *AqHomeData_GetOrCreateValueForDriverWithTemplate(AQHOME_DATA *aqh, v=AQH_Storage_GetValueByNameForSystem(aqh->storage, GWEN_Buffer_GetStart(buf)); if (v==NULL) { if (AQH_IpcEndpoint_GetPermissions(epDriver) & AQH_IPCENDPOINT_PERMS_ADDVALUE) { - /* TODO: get or create device */ + AQH_DEVICE *device; + DBG_INFO(AQH_LOGDOMAIN, "Creating value \"%s\"", GWEN_Buffer_GetStart(buf)); + device=(deviceNameForDriver && *deviceNameForDriver)?_getOrCreateDeviceForDriver(aqh, epDriver, deviceNameForDriver):NULL; + v=AQH_Value_new(); AQH_Value_SetDriver(v, serviceName); AQH_Value_SetNameForDriver(v, AQH_Value_GetNameForDriver(valueTemplate)); @@ -163,6 +170,10 @@ AQH_VALUE *AqHomeData_GetOrCreateValueForDriverWithTemplate(AQHOME_DATA *aqh, AQH_Value_SetValueUnits(v, AQH_Value_GetValueUnits(valueTemplate)); AQH_Value_SetValueType(v, AQH_Value_GetValueType(valueTemplate)); AQH_Value_SetTimestampCreation(v, (uint64_t) time(NULL)); + if (device) { + AQH_Value_SetDeviceNameForSystem(v, AQH_Device_GetNameForSystem(device)); + AQH_Value_SetDeviceNameForDriver(v, AQH_Device_GetNameForDriver(device)); + } AQH_Storage_AddValue(aqh->storage, v); } else { @@ -177,6 +188,39 @@ AQH_VALUE *AqHomeData_GetOrCreateValueForDriverWithTemplate(AQHOME_DATA *aqh, +AQH_DEVICE *_getOrCreateDeviceForDriver(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *epDriver, const char *nameForDriver) +{ + const char *serviceName; + AQH_DEVICE *device; + GWEN_BUFFER *buf; + + serviceName=AQH_IpcEndpoint_GetServiceName(epDriver); + + buf=GWEN_Buffer_new(0, 256, 0, 1); + GWEN_Buffer_AppendArgs(buf, "%s/%s", (serviceName && *serviceName)?serviceName:"unknown", nameForDriver); + + device=AQH_Storage_GetDeviceByNameForSystem(aqh->storage, GWEN_Buffer_GetStart(buf)); + if (device==NULL) { + if (AQH_IpcEndpoint_GetPermissions(epDriver) & AQH_IPCENDPOINT_PERMS_ADDDEVICE) { + DBG_INFO(AQH_LOGDOMAIN, "Creating device \"%s\"", GWEN_Buffer_GetStart(buf)); + device=AQH_Device_new(); + AQH_Device_SetDriver(device, serviceName); + AQH_Device_SetNameForDriver(device, nameForDriver); + AQH_Device_SetNameForSystem(device, GWEN_Buffer_GetStart(buf)); + AQH_Storage_AddDevice(aqh->storage, device); + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "No permissions to create device \"%s\"", GWEN_Buffer_GetStart(buf)); + GWEN_Buffer_free(buf); + return NULL; + } + } + GWEN_Buffer_free(buf); + return device; +} + + + void _readAndHandleIpcMessages(AQHOME_DATA *aqh) { if (aqh->ipcdEndpoint) { @@ -207,19 +251,27 @@ void _handleIpcEndpoint(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep) void _handleIpcMsg(AQHOME_DATA *aqh, GWEN_MSG_ENDPOINT *ep, GWEN_MSG *msg) { uint16_t code; + uint8_t protoId; /* exec IPC message */ code=GWEN_IpcMsg_GetCode(msg); - DBG_DEBUG(AQH_LOGDOMAIN, "Received IPC packet %d (%x)", (int) code, code); - switch(code) { - case AQH_MSGTYPE_IPC_DATA_CONNECT_REQ: AqHomeData_HandleConnect(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_UPDATEDATA: AqHomeData_HandleUpdateData(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ: AqHomeData_HandleGetValues(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_GETDATA_REQ: AqHomeData_HandleGetDataPoints(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ: AqHomeData_HandleGetLastDataPoint(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_SETDATA: AqHomeData_HandleSetData(aqh, ep, msg); break; - case AQH_MSGTYPE_IPC_DATA_ADDVALUE: AqHomeData_HandleAddValue(aqh, ep, msg); break; - default: break; + protoId=GWEN_IpcMsg_GetProtoId(msg); + if (protoId==AQH_IPC_PROTOCOL_DATA_ID) { + DBG_DEBUG(AQH_LOGDOMAIN, "Received IPC packet %d (%x)", (int) code, code); + switch(code) { + case AQH_MSGTYPE_IPC_DATA_CONNECT_REQ: AqHomeData_HandleConnect(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_UPDATEDATA: AqHomeData_HandleUpdateData(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ: AqHomeData_HandleGetValues(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_GETDATA_REQ: AqHomeData_HandleGetDataPoints(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ: AqHomeData_HandleGetLastDataPoint(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_SETDATA: AqHomeData_HandleSetData(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_ADDVALUE: AqHomeData_HandleAddValue(aqh, ep, msg); break; + case AQH_MSGTYPE_IPC_DATA_GETDEVICES_REQ: AqHomeData_HandleGetDevices(aqh, ep, msg); break; + default: break; + } + } + else { + DBG_ERROR(NULL, "Invalid IPC protocol %d (%02x)", protoId, protoId); } } diff --git a/apps/aqhome-tool/data/0BUILD b/apps/aqhome-tool/data/0BUILD index 055e792..e03ccb4 100644 --- a/apps/aqhome-tool/data/0BUILD +++ b/apps/aqhome-tool/data/0BUILD @@ -34,6 +34,7 @@ getvalues.h + getdevices.h adddata.h getdatapoints.h getlastdatapoint.h @@ -44,6 +45,7 @@ $(local/typefiles) getvalues.c + getdevices.c adddata.c getdatapoints.c getlastdatapoint.c diff --git a/apps/aqhome-tool/data/getdevices.c b/apps/aqhome-tool/data/getdevices.c new file mode 100644 index 0000000..4337aa5 --- /dev/null +++ b/apps/aqhome-tool/data/getdevices.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * 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 "./getdevices.h" +#include "../utils.h" + +#include "aqhome/msg/msg_node.h" +#include "aqhome/ipc/msg_ipc_result.h" +#include "aqhome/ipc/data/msg_data_devices.h" +#include "aqhome/ipc/data/ipc_data.h" + +#include +#include +#include +#include + +#include +#include + + +#define I18S(msg) msg +#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg) + + +static int _doGetDevices(GWEN_DB_NODE *dbArgs); +static void _sendCommand(GWEN_MSG_ENDPOINT *epTcp); + + + + +int AQH_Tool_GetDevices(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv) +{ + GWEN_DB_NODE *dbLocalArgs; + int rv; + const GWEN_ARGS args[]= { + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Char, /* type */ + "tcpAddress", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "t", /* short option */ + "tcpaddress", /* long option */ + I18S("Specify TCP address to connect to (defaults to 127.0.0.1)"), + I18S("Specify TCP address to connect to (defaults to 127.0.0.1)") + }, + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Int, /* type */ + "tcpPort", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "P", /* short option */ + "tcpport", /* long option */ + I18S("Specify the TCP port to listen on"), + I18S("Specify the TCP port to listen on") + }, + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Int, /* type */ + "timeout", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "T", /* short option */ + NULL, /* long option */ + I18S("Specify timeout in seconds for response"), + I18S("Specify timeout in seconds for response") + }, + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Char, /* type */ + "clientId", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "c", /* short option */ + "clientid", /* long option */ + I18S("Specify CLIENTID"), + I18S("Specify CLIENTID") + }, + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Char, /* type */ + "userId", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "u", /* short option */ + "userid", /* long option */ + I18S("Specify user id"), + I18S("Specify user id") + }, + { + GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ + GWEN_ArgsType_Char, /* type */ + "password", /* name */ + 0, /* minnum */ + 1, /* maxnum */ + "p", /* short option */ + "password", /* long option */ + I18S("Specify service password"), + I18S("Specify service password") + }, + { + GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */ + GWEN_ArgsType_Int, /* type */ + "help", /* name */ + 0, /* minnum */ + 0, /* maxnum */ + "h", /* short option */ + "help", /* long option */ + "Show this help screen", /* short description */ + "Show this help screen" /* long description */ + } + }; + + dbLocalArgs=GWEN_DB_GetGroup(dbGlobalArgs, GWEN_DB_FLAGS_DEFAULT, "local"); + rv=GWEN_Args_Check(argc, argv, 1, + GWEN_ARGS_MODE_ALLOW_FREEPARAM, + args, + dbLocalArgs); + if (rv==GWEN_ARGS_RESULT_ERROR) { + fprintf(stderr, "ERROR: Could not parse arguments\n"); + return 1; + } + else if (rv==GWEN_ARGS_RESULT_HELP) { + GWEN_BUFFER *ubuf; + + ubuf=GWEN_Buffer_new(0, 1024, 0, 1); + if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) { + fprintf(stderr, "ERROR: Could not create help string\n"); + return 1; + } + fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(ubuf)); + GWEN_Buffer_free(ubuf); + return 0; + } + + return _doGetDevices(dbLocalArgs); +} + + + +int _doGetDevices(GWEN_DB_NODE *dbArgs) +{ + GWEN_MSG_ENDPOINT *epTcp; + int timeoutInSeconds; + GWEN_MSG *msg; + + timeoutInSeconds=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 5); + + epTcp=Utils_OpenConnection(dbArgs, 0, timeoutInSeconds); + if (epTcp==NULL) { + DBG_ERROR(NULL, "ERROR creating TCP connection"); + return 2; + } + + /*fprintf(stdout, "Sending GetDevices request\n");*/ + + _sendCommand(epTcp); + + for (;;) { + uint16_t code; + + msg=Utils_WaitForSpecificIpcMessage(epTcp, AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP, timeoutInSeconds); + if (msg==NULL) { + DBG_ERROR(NULL, "No response received"); + return 2; + } + code=GWEN_IpcMsg_GetCode(msg); + if (code==AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP) { + AQH_VALUE_LIST *deviceList; + + AQH_DevicesDataIpcMsg_Parse(msg, 0); + deviceList=AQH_DevicesDataIpcMsg_ReadDeviceList(msg); + if (deviceList) { + AQH_DEVICE *device; + + device=AQH_Device_List_First(deviceList); + while(device) { + uint64_t deviceId; + const char *deviceName; + + deviceId=AQH_Device_GetId(device); + deviceName=AQH_Device_GetNameForSystem(device); + + fprintf(stdout, "%lu\t%s\n", (unsigned long int) deviceId, deviceName?deviceName:""); + + device=AQH_Device_List_Next(device); + } + AQH_Device_List_free(deviceList); + } + + if (AQH_DevicesDataIpcMsg_GetFlags(msg) & AQH_MSGDATA_DEVICES_FLAGS_LASTMSG) { + DBG_INFO(NULL, "Last message received"); + break; + } + } + else if (code==AQH_MSGTYPE_IPC_DATA_RESULT) { + uint32_t resultCode; + + resultCode=AQH_ResultIpcMsg_GetResultCode(msg); + fprintf(stderr, "ERROR: %d\n", resultCode); + GWEN_MsgEndpoint_free(epTcp); + return 3; + } + else { + DBG_INFO(NULL, "Unexpected message \"%d\"", code); + GWEN_MsgEndpoint_free(epTcp); + return 3; + } + } /* for */ + + GWEN_MsgEndpoint_free(epTcp); + return 0; +} + + + +void _sendCommand(GWEN_MSG_ENDPOINT *epTcp) +{ + GWEN_MSG *msgOut; + + msgOut=GWEN_IpcMsg_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, AQH_MSGTYPE_IPC_DATA_GETDEVICES_REQ, 0, NULL); + GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut); +} + + + + + + diff --git a/apps/aqhome-tool/nodes/getdevices.h b/apps/aqhome-tool/data/getdevices.h similarity index 86% rename from apps/aqhome-tool/nodes/getdevices.h rename to apps/aqhome-tool/data/getdevices.h index e6949d6..6e2a387 100644 --- a/apps/aqhome-tool/nodes/getdevices.h +++ b/apps/aqhome-tool/data/getdevices.h @@ -13,7 +13,8 @@ #include -int AQH_Tool_GetDevices(GWEN_DB_NODE *dbArgs, int argc, char **argv); + +int AQH_Tool_GetDevices(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv); #endif diff --git a/apps/aqhome-tool/main.c b/apps/aqhome-tool/main.c index f323116..6a40b95 100644 --- a/apps/aqhome-tool/main.c +++ b/apps/aqhome-tool/main.c @@ -12,8 +12,9 @@ #include "./nodes/ping.h" #include "./nodes/flash.h" -#include "./nodes/getdevices.h" +#include "./nodes/getnodes.h" #include "./data/getvalues.h" +#include "./data/getdevices.h" #include "./data/adddata.h" #include "./data/getdatapoints.h" #include "./data/getlastdatapoint.h" @@ -73,8 +74,9 @@ int main(int argc, char **argv) const GWEN_FUNCS cmdDefArray[]= { GWEN_FE_DAH("ping", AQH_Tool_Ping, I18N("Ping a given node on the network")), GWEN_FE_DAH("flash", AQH_Tool_Flash, I18N("Flash a given node on the network")), - GWEN_FE_DAH("getdevices", AQH_Tool_GetDevices, I18N("Request list of known devices on the network")), + GWEN_FE_DAH("getnodes", AQH_Tool_GetNodes, I18N("Request list of known devices on the network")), GWEN_FE_DAH("getvalues", AQH_Tool_GetValues, I18N("Request list of known values on the data server")), + GWEN_FE_DAH("getdevices", AQH_Tool_GetDevices, I18N("Request list of known devices on the data server")), GWEN_FE_DAH("adddata", AQH_Tool_AddDataPoint, I18N("Send a datapoint to the data server")), GWEN_FE_DAH("getdata", AQH_Tool_GetDataPoints, I18N("Request list of datapoints for a value on the data server")), GWEN_FE_DAH("getlastdata", AQH_Tool_GetLastDataPoint, I18N("Request last datapoint for a value on the data server")), diff --git a/apps/aqhome-tool/nodes/0BUILD b/apps/aqhome-tool/nodes/0BUILD index 3f8c236..7563f9a 100644 --- a/apps/aqhome-tool/nodes/0BUILD +++ b/apps/aqhome-tool/nodes/0BUILD @@ -35,7 +35,7 @@ ping.h flash.h - getdevices.h + getnodes.h @@ -43,7 +43,7 @@ ping.c flash.c - getdevices.c + getnodes.c diff --git a/apps/aqhome-tool/nodes/getdevices.c b/apps/aqhome-tool/nodes/getnodes.c similarity index 96% rename from apps/aqhome-tool/nodes/getdevices.c rename to apps/aqhome-tool/nodes/getnodes.c index 8a378fe..13e8b80 100644 --- a/apps/aqhome-tool/nodes/getdevices.c +++ b/apps/aqhome-tool/nodes/getnodes.c @@ -10,7 +10,7 @@ # include #endif -#include "./getdevices.h" +#include "./getnodes.h" #include "../utils.h" #include "aqhome/ipc/endpoint_ipc.h" @@ -33,12 +33,12 @@ -static int _doGetDevices(GWEN_DB_NODE *dbArgs); +static int _doGetNodes(GWEN_DB_NODE *dbArgs); static int _sendGetDevices(GWEN_MSG_ENDPOINT *epTcp); -int AQH_Tool_GetDevices(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv) +int AQH_Tool_GetNodes(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv) { GWEN_DB_NODE *dbLocalArgs; int rv; @@ -111,12 +111,12 @@ int AQH_Tool_GetDevices(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv) return 0; } - return _doGetDevices(dbLocalArgs); + return _doGetNodes(dbLocalArgs); } -int _doGetDevices(GWEN_DB_NODE *dbArgs) +int _doGetNodes(GWEN_DB_NODE *dbArgs) { GWEN_MSG_ENDPOINT *epTcp; int rv; diff --git a/apps/aqhome-tool/nodes/getnodes.h b/apps/aqhome-tool/nodes/getnodes.h new file mode 100644 index 0000000..e9f634b --- /dev/null +++ b/apps/aqhome-tool/nodes/getnodes.h @@ -0,0 +1,20 @@ +/**************************************************************************** + * 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 AQHOME_TOOL_GETNODES_H +#define AQHOME_TOOL_GETNODES_H + + +#include + + +int AQH_Tool_GetNodes(GWEN_DB_NODE *dbArgs, int argc, char **argv); + + +#endif + diff --git a/aqhome/data/0BUILD b/aqhome/data/0BUILD index e22b5a9..ebe657f 100644 --- a/aqhome/data/0BUILD +++ b/aqhome/data/0BUILD @@ -29,19 +29,23 @@ value.t2d + device.t2d value.c + device.c value.h + device.h value_p.h + device_p.h diff --git a/aqhome/data/device.t2d b/aqhome/data/device.t2d index 64eec70..6c245ae 100644 --- a/aqhome/data/device.t2d +++ b/aqhome/data/device.t2d @@ -37,6 +37,13 @@ with_getbymember + + 0 + 0 + public + own + + 0 0 @@ -94,6 +101,13 @@ own + + public + none + 0 + 0 + + diff --git a/aqhome/data/storage.c b/aqhome/data/storage.c index 41cc72f..d35a611 100644 --- a/aqhome/data/storage.c +++ b/aqhome/data/storage.c @@ -49,6 +49,7 @@ AQH_STORAGE *AQH_Storage_new(void) AQH_STORAGE *sto; GWEN_NEW_OBJECT(AQH_STORAGE, sto); + sto->deviceList=AQH_Device_List_new(); sto->valueList=AQH_Value_List_new(); sto->dataFileList=AQH_DataFile_List_new(); @@ -62,6 +63,7 @@ void AQH_Storage_free(AQH_STORAGE *sto) if (sto) { AQH_DataFile_List_free(sto->dataFileList); AQH_Value_List_free(sto->valueList); + AQH_Device_List_free(sto->deviceList); free(sto->dataFileFolder); free(sto->stateFile); @@ -123,6 +125,44 @@ AQH_VALUE *AQH_Storage_GetValueByNameForSystem(const AQH_STORAGE *sto, const cha +void AQH_Storage_AddDevice(AQH_STORAGE *sto, AQH_DEVICE *device) +{ + if (sto && device) { + uint64_t id; + + id=++(sto->lastDeviceId); + AQH_Device_SetId(device, id); + AQH_Device_List_Add(device, sto->deviceList); + AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); + } +} + + + +AQH_DEVICE_LIST *AQH_Storage_GetDeviceList(const AQH_STORAGE *sto) +{ + return sto?sto->deviceList:NULL; +} + + + +AQH_DEVICE *AQH_Storage_GetDeviceById(const AQH_STORAGE *sto, uint64_t id) +{ + return sto?AQH_Device_List_GetById(sto->deviceList, id):NULL; +} + + + +AQH_DEVICE *AQH_Storage_GetDeviceByNameForSystem(const AQH_STORAGE *sto, const char *s) +{ + return sto?AQH_Device_List_GetByNameForSystem(sto->deviceList, s):NULL; +} + + + + + + uint32_t AQH_Storage_GetRuntimeFlags(const AQH_STORAGE *sto) { return sto?sto->runtimeFlags:0; diff --git a/aqhome/data/storage.h b/aqhome/data/storage.h index d77bc2e..a767b9c 100644 --- a/aqhome/data/storage.h +++ b/aqhome/data/storage.h @@ -31,7 +31,7 @@ typedef struct AQH_STORAGE AQH_STORAGE; #include "aqhome/data/device.h" #include "aqhome/data/mqtttopic.h" #include "aqhome/data/value.h" -#include "aqhome/data/datapoint.h" +#include "aqhome/data/device.h" #define AQH_STORAGE_RTFLAGS_MODIFIED 0x0001 @@ -54,6 +54,11 @@ 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_GetValueByNameForSystem(const AQH_STORAGE *sto, const char *s); +AQHOME_API void AQH_Storage_AddDevice(AQH_STORAGE *sto, AQH_DEVICE *device); +AQHOME_API AQH_DEVICE_LIST *AQH_Storage_GetDeviceList(const AQH_STORAGE *sto); +AQHOME_API AQH_DEVICE *AQH_Storage_GetDeviceById(const AQH_STORAGE *sto, uint64_t id); +AQHOME_API AQH_DEVICE *AQH_Storage_GetDeviceByNameForSystem(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); diff --git a/aqhome/data/storage_p.h b/aqhome/data/storage_p.h index a2c8492..9c76b55 100644 --- a/aqhome/data/storage_p.h +++ b/aqhome/data/storage_p.h @@ -14,17 +14,22 @@ #include "aqhome/data/datafile.h" -#define AQH_STORAGE_XML_ELEMENTNAME_LASTIDS "lastIds" +#define AQH_STORAGE_XML_ELEMENTNAME_LASTIDS "lastIds" -#define AQH_STORAGE_XML_ELEMENTNAME_VALUES "values" -#define AQH_STORAGE_XML_ELEMENTNAME_VALUE "value" +#define AQH_STORAGE_XML_ELEMENTNAME_VALUES "values" +#define AQH_STORAGE_XML_ELEMENTNAME_VALUE "value" + +#define AQH_STORAGE_XML_ELEMENTNAME_DEVICES "devices" +#define AQH_STORAGE_XML_ELEMENTNAME_DEVICE "device" struct AQH_STORAGE { AQH_VALUE_LIST *valueList; + AQH_DEVICE_LIST *deviceList; uint64_t lastValueId; + uint64_t lastDeviceId; char *stateFile; char *dataFileFolder; diff --git a/aqhome/data/storage_readxml.c b/aqhome/data/storage_readxml.c index 2eb81c4..d6e766f 100644 --- a/aqhome/data/storage_readxml.c +++ b/aqhome/data/storage_readxml.c @@ -27,6 +27,7 @@ static void _readLastIdsFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); static void _readValuesFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); +static void _readDevicesFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); @@ -50,6 +51,7 @@ int AQH_Storage_ReadStateFile(AQH_STORAGE *sto, const char *sFilename) _readLastIdsFromXml(sto, rootNode); _readValuesFromXml(sto, rootNode); + _readDevicesFromXml(sto, rootNode); GWEN_XMLNode_free(rootNode); @@ -65,6 +67,7 @@ void _readLastIdsFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) nLastIds=GWEN_XMLNode_FindFirstTag(rootNode, AQH_STORAGE_XML_ELEMENTNAME_LASTIDS, NULL, NULL); if (nLastIds) { sto->lastValueId=GWEN_XMLNode_GetIntValue(nLastIds, "lastValueId", 0); + sto->lastDeviceId=GWEN_XMLNode_GetIntValue(nLastIds, "lastDeviceId", 0); } else { sto->lastValueId=0; @@ -96,6 +99,29 @@ void _readValuesFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) +void _readDevicesFromXml(AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) +{ + GWEN_XMLNODE *nDevices; + + nDevices=GWEN_XMLNode_FindFirstTag(rootNode, AQH_STORAGE_XML_ELEMENTNAME_DEVICES, NULL, NULL); + if (nDevices) { + GWEN_XMLNODE *nDevice; + + nDevice=GWEN_XMLNode_FindFirstTag(nDevices, AQH_STORAGE_XML_ELEMENTNAME_DEVICE, NULL, NULL); + while(nDevice) { + AQH_DEVICE *device; + + device=AQH_Device_fromXml(nDevice); + if (device) { + AQH_Device_List_Add(device, sto->deviceList); + } + nDevice=GWEN_XMLNode_FindNextTag(nDevice, AQH_STORAGE_XML_ELEMENTNAME_DEVICE, NULL, NULL); + } + } +} + + + diff --git a/aqhome/data/storage_writexml.c b/aqhome/data/storage_writexml.c index e434e99..fa5d81f 100644 --- a/aqhome/data/storage_writexml.c +++ b/aqhome/data/storage_writexml.c @@ -32,6 +32,7 @@ static void _writeLastIdsToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); static void _writeValuesToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); +static void _writeDevicesToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode); @@ -49,6 +50,7 @@ int AQH_Storage_WriteStateFile(const AQH_STORAGE *sto, const char *sFilename) rootNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "root"); _writeLastIdsToXml(sto, rootNode); _writeValuesToXml(sto, rootNode); + _writeDevicesToXml(sto, rootNode); nbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nbuf, sFilename); @@ -56,7 +58,7 @@ int AQH_Storage_WriteStateFile(const AQH_STORAGE *sto, const char *sFilename) unlink(GWEN_Buffer_GetStart(nbuf)); rv=GWEN_XMLNode_WriteFile(rootNode, GWEN_Buffer_GetStart(nbuf), - GWEN_XML_FLAGS_SIMPLE | GWEN_XML_FLAGS_HANDLE_HEADERS | GWEN_XML_FLAGS_INDENT); + GWEN_XML_FLAGS_SIMPLE | GWEN_XML_FLAGS_HANDLE_HEADERS | GWEN_XML_FLAGS_INDENT); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error writing XML file \"%s\": %d", GWEN_Buffer_GetStart(nbuf), rv); GWEN_Buffer_free(nbuf); @@ -83,6 +85,7 @@ void _writeLastIdsToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) nLastIds=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, AQH_STORAGE_XML_ELEMENTNAME_LASTIDS); GWEN_XMLNode_SetIntValue(nLastIds, "lastValueId", sto->lastValueId); + GWEN_XMLNode_SetIntValue(nLastIds, "lastDeviceId", sto->lastDeviceId); GWEN_XMLNode_AddChild(rootNode, nLastIds); } @@ -110,6 +113,27 @@ void _writeValuesToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) +void _writeDevicesToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode) +{ + GWEN_XMLNODE *nElems; + AQH_DEVICE *elem; + + nElems=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, AQH_STORAGE_XML_ELEMENTNAME_DEVICES); + + elem=AQH_Device_List_First(sto->deviceList); + while(elem) { + GWEN_XMLNODE *nElem; + + nElem=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, AQH_STORAGE_XML_ELEMENTNAME_DEVICE); + AQH_Device_toXml(elem, nElem); + GWEN_XMLNode_AddChild(nElems, nElem); + elem=AQH_Device_List_Next(elem); + } + GWEN_XMLNode_AddChild(rootNode, nElems); +} + + + diff --git a/aqhome/ipc/data/0BUILD b/aqhome/ipc/data/0BUILD index ca213aa..732f34f 100644 --- a/aqhome/ipc/data/0BUILD +++ b/aqhome/ipc/data/0BUILD @@ -47,6 +47,7 @@ ipc_data.h msg_data_values.h + msg_data_devices.h msg_data_datapoints.h msg_data_connect.h msg_data_multidata.h @@ -63,6 +64,7 @@ ipc_data.c msg_data_values.c + msg_data_devices.c msg_data_datapoints.c msg_data_connect.c msg_data_multidata.c diff --git a/aqhome/ipc/data/ipc_data.c b/aqhome/ipc/data/ipc_data.c index 91bcdee..d03e18b 100644 --- a/aqhome/ipc/data/ipc_data.c +++ b/aqhome/ipc/data/ipc_data.c @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -24,15 +23,28 @@ * ------------------------------------------------------------------------------------------------ */ -#define AQH_IPCDATA_VALUE_TAGS_ID 0x01 -#define AQH_IPCDATA_VALUE_TAGS_DRIVER 0x02 -#define AQH_IPCDATA_VALUE_TAGS_NAMEFORDRIVER 0x03 -#define AQH_IPCDATA_VALUE_TAGS_NAMEFORSYSTEM 0x04 -#define AQH_IPCDATA_VALUE_TAGS_TYPE 0x05 -#define AQH_IPCDATA_VALUE_TAGS_UNITS 0x06 -#define AQH_IPCDATA_VALUE_TAGS_TIMEOFCREATION 0x07 -#define AQH_IPCDATA_VALUE_TAGS_DEVFORDRIVER 0x08 -#define AQH_IPCDATA_VALUE_TAGS_DEVFORSYSTEM 0x09 +#define AQH_IPCDATA_VALUE_TAGS_ID 0x01 +#define AQH_IPCDATA_VALUE_TAGS_DRIVER 0x02 +#define AQH_IPCDATA_VALUE_TAGS_NAMEFORDRIVER 0x03 +#define AQH_IPCDATA_VALUE_TAGS_NAMEFORSYSTEM 0x04 +#define AQH_IPCDATA_VALUE_TAGS_TYPE 0x05 +#define AQH_IPCDATA_VALUE_TAGS_UNITS 0x06 +#define AQH_IPCDATA_VALUE_TAGS_TIMEOFCREATION 0x07 +#define AQH_IPCDATA_VALUE_TAGS_DEVFORDRIVER 0x08 +#define AQH_IPCDATA_VALUE_TAGS_DEVFORSYSTEM 0x09 + +#define AQH_IPCDATA_DEVICE_TAGS_ID 0x01 +#define AQH_IPCDATA_DEVICE_TAGS_DRIVER 0x02 +#define AQH_IPCDATA_DEVICE_TAGS_ROOMNAME 0x03 +#define AQH_IPCDATA_DEVICE_TAGS_NAMEFORDRIVER 0x04 +#define AQH_IPCDATA_DEVICE_TAGS_NAMEFORSYSTEM 0x05 +#define AQH_IPCDATA_DEVICE_TAGS_NAMEFORGUI 0x06 +#define AQH_IPCDATA_DEVICE_TAGS_LOCATION 0x07 +#define AQH_IPCDATA_DEVICE_TAGS_DESCRIPTION 0x08 +#define AQH_IPCDATA_DEVICE_TAGS_DEVTYPE 0x09 +#define AQH_IPCDATA_DEVICE_TAGS_MANUFACTURER 0x0a +#define AQH_IPCDATA_DEVICE_TAGS_TIMEOFCREATION 0x0b + @@ -43,6 +55,8 @@ static void _writeValueFieldsAsTagsToBuffer(const AQH_VALUE *value, GWEN_BUFFER *buf); static AQH_VALUE *_readValueFromTag(const uint8_t *ptr, uint32_t len); +static void _writeDeviceFieldsAsTagsToBuffer(const AQH_DEVICE *device, GWEN_BUFFER *buf); +static AQH_DEVICE *_readDeviceFromTag(const uint8_t *ptr, uint32_t len); @@ -101,6 +115,54 @@ int AQH_DataIpc_WriteValueAsTagToBuffer(unsigned int tagType, const AQH_VALUE *v +int AQH_DataIpc_WriteDeviceListAsTagsToBuffer(unsigned int tagType, const AQH_DEVICE_LIST *deviceList, GWEN_BUFFER *buf) +{ + if (deviceList) { + const AQH_DEVICE *device; + + device=AQH_Device_List_First(deviceList); + while(device) { + int rv; + + rv=AQH_DataIpc_WriteDeviceAsTagToBuffer(tagType, device, buf); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + GWEN_Buffer_free(buf); + return rv; + } + + device=AQH_Device_List_Next(device); + } + } + return 0; +} + + + +int AQH_DataIpc_WriteDeviceAsTagToBuffer(unsigned int tagType, const AQH_DEVICE *device, GWEN_BUFFER *buf) +{ + int startPos; + int rv; + + startPos=GWEN_Tag16_StartTagInBuffer(tagType, buf); + if (startPos<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", startPos); + return startPos; + } + + _writeDeviceFieldsAsTagsToBuffer(device, buf); + + rv=GWEN_Tag16_EndTagInBuffer(startPos, buf); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + return rv; + } + + return 0; +} + + + void _writeValueFieldsAsTagsToBuffer(const AQH_VALUE *value, GWEN_BUFFER *buf) { const char *s; @@ -185,6 +247,50 @@ AQH_VALUE *AQH_DataIpc_ReadValueFromTagList(const GWEN_TAG16_LIST *tagList, unsi +AQH_DEVICE_LIST *AQH_DataIpc_ReadDevicesFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType) +{ + AQH_DEVICE_LIST *deviceList; + const GWEN_TAG16 *tag; + + deviceList=AQH_Device_List_new(); + tag=GWEN_Tag16_List_First(tagList); + while(tag) { + unsigned int tagType; + AQH_DEVICE *device; + + tagType=GWEN_Tag16_GetTagType(tag); + if (tagType==wantedTagType) { + device=_readDeviceFromTag((const uint8_t*) GWEN_Tag16_GetTagData(tag), (uint32_t) GWEN_Tag16_GetTagLength(tag)); + if (device) + AQH_Device_List_Add(device, deviceList); + } + + tag=GWEN_Tag16_List_Next(tag); + } + + if (AQH_Device_List_GetCount(deviceList)<1) { + AQH_Device_List_free(deviceList); + return NULL; + } + + return deviceList; +} + + + +AQH_DEVICE *AQH_DataIpc_ReadDeviceFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType) +{ + if (tagList) { + const GWEN_TAG16 *tag; + + tag=GWEN_Tag16_List_FindFirstByTagType(tagList, wantedTagType); + return tag?_readDeviceFromTag((const uint8_t*) GWEN_Tag16_GetTagData(tag), (uint32_t) GWEN_Tag16_GetTagLength(tag)):NULL; + } + return NULL; +} + + + AQH_VALUE *_readValueFromTag(const uint8_t *ptr, uint32_t len) { GWEN_TAG16_LIST *tagList; @@ -256,3 +362,134 @@ AQH_VALUE *_readValueFromTag(const uint8_t *ptr, uint32_t len) +void _writeDeviceFieldsAsTagsToBuffer(const AQH_DEVICE *device, GWEN_BUFFER *buf) +{ + const char *s; + + GWEN_Tag16_WriteUint64TagToBuffer(AQH_IPCDATA_DEVICE_TAGS_ID, AQH_Device_GetId(device), buf); + + s=AQH_Device_GetDriver(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_DRIVER, s, buf); + + s=AQH_Device_GetRoomName(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_ROOMNAME, s, buf); + + s=AQH_Device_GetNameForDriver(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_NAMEFORDRIVER, s, buf); + + s=AQH_Device_GetNameForSystem(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_NAMEFORSYSTEM, s, buf); + + s=AQH_Device_GetNameForGui(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_NAMEFORGUI, s, buf); + + s=AQH_Device_GetLocation(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_LOCATION, s, buf); + + s=AQH_Device_GetDescription(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_DESCRIPTION, s, buf); + + s=AQH_Device_GetDeviceType(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_DEVTYPE, s, buf); + + s=AQH_Device_GetManufacturer(device); + if (s && *s) + GWEN_Tag16_WriteStringTagToBuffer(AQH_IPCDATA_DEVICE_TAGS_MANUFACTURER, s, buf); + + GWEN_Tag16_WriteUint64TagToBuffer(AQH_IPCDATA_DEVICE_TAGS_TIMEOFCREATION, AQH_Device_GetTimestampCreation(device), buf); +} + + + +AQH_DEVICE *_readDeviceFromTag(const uint8_t *ptr, uint32_t len) +{ + GWEN_TAG16_LIST *tagList; + + tagList=GWEN_Tag16_List_fromBuffer(ptr, len, 0); + if (tagList) { + GWEN_TAG16 *tag; + AQH_DEVICE *device; + + device=AQH_Device_new(); + tag=GWEN_Tag16_List_First(tagList); + while(tag) { + unsigned int tagType; + char *s; + + tagType=GWEN_Tag16_GetTagType(tag); + switch(tagType) { + case AQH_IPCDATA_DEVICE_TAGS_ID: + AQH_Device_SetId(device, GWEN_Tag16_GetTagDataAsUint64(tag, 0)); + break; + case AQH_IPCDATA_DEVICE_TAGS_DRIVER: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetDriver(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_ROOMNAME: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetRoomName(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_NAMEFORDRIVER: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetNameForDriver(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_NAMEFORSYSTEM: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetNameForSystem(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_NAMEFORGUI: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetNameForGui(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_LOCATION: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetLocation(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_DESCRIPTION: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetDescription(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_DEVTYPE: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetDeviceType(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_MANUFACTURER: + s=GWEN_Tag16_GetTagDataAsNewString(tag, NULL); + AQH_Device_SetManufacturer(device, s); + free(s); + break; + case AQH_IPCDATA_DEVICE_TAGS_TIMEOFCREATION: + AQH_Device_SetTimestampCreation(device, GWEN_Tag16_GetTagDataAsUint64(tag, 0)); + break; + default: + DBG_INFO(AQH_LOGDOMAIN, "Unhandled tag typ %d (%02x)", tagType, tagType); + break; + } + tag=GWEN_Tag16_List_Next(tag); + } + GWEN_Tag16_List_free(tagList); + return device; + } + + return NULL; +} + + + + diff --git a/aqhome/ipc/data/ipc_data.h b/aqhome/ipc/data/ipc_data.h index 094d7d0..997cb2b 100644 --- a/aqhome/ipc/data/ipc_data.h +++ b/aqhome/ipc/data/ipc_data.h @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -30,18 +31,23 @@ #define AQH_MSGTYPE_IPC_DATA_UPDATEDATA 0x100 /* AQH_MultiDataDataIpcMsg */ #define AQH_MSGTYPE_IPC_DATA_DATACHANGED 0x200 /* AQH_MultiDataDataIpcMsg */ -#define AQH_MSGTYPE_IPC_DATA_SETDATA 0x300 /* AQH_SingleDataDataIpcMsg */ +#define AQH_MSGTYPE_IPC_DATA_SETDATA 0x300 /* AQH_MultiDataDataIpcMsg */ #define AQH_MSGTYPE_IPC_DATA_ADDVALUE 0x400 /* AQH_AddValueDataIpcMsg */ #define AQH_MSGTYPE_IPC_DATA_GETDATA_REQ 0x500 /* AQH_GetDataDataIpcMsg */ -#define AQH_MSGTYPE_IPC_DATA_GETDATA_RSP 0x600 /* AQH_DataPointsDataIpcMsg */ /* TODO */ +#define AQH_MSGTYPE_IPC_DATA_GETDATA_RSP 0x600 /* AQH_MultiDataDataIpcMsg */ -#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ 0x700 /* AQH_ValueDataIpcMsg */ -#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_RSP 0x800 /* AQH_SingleDataDataIpcMsg */ +#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_REQ 0x700 /* AQH_GetDataDataIpcMsg */ +#define AQH_MSGTYPE_IPC_DATA_GETLASTDATA_RSP 0x800 /* AQH_MultiDataDataIpcMsg */ #define AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ 0x900 /* GWEN_IpcMsg */ -#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0xa00 /* AQH_ValuesDataIpcMsg */ /* TODO */ +#define AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP 0xa00 /* AQH_ValuesDataIpcMsg */ + +#define AQH_MSGTYPE_IPC_DATA_GETDEVICES_REQ 0xb00 /* GWEN_IpcMsg */ +#define AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP 0xc00 /* AQH_DevicesDataIpcMsg */ + +#define AQH_MSGTYPE_IPC_DATA_MODDEVICES_REQ 0xd00 /* AQH_DevicesDataIpcMsg */ @@ -53,6 +59,11 @@ AQHOME_API int AQH_DataIpc_WriteValueAsTagToBuffer(unsigned int tagType, const A AQHOME_API AQH_VALUE_LIST *AQH_DataIpc_ReadValuesFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType); AQHOME_API AQH_VALUE *AQH_DataIpc_ReadValueFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType); +AQHOME_API int AQH_DataIpc_WriteDeviceListAsTagsToBuffer(unsigned int tagType, const AQH_DEVICE_LIST *deviceList, GWEN_BUFFER *buf); +AQHOME_API int AQH_DataIpc_WriteDeviceAsTagToBuffer(unsigned int tagType, const AQH_DEVICE *device, GWEN_BUFFER *buf); +AQHOME_API AQH_DEVICE_LIST *AQH_DataIpc_ReadDevicesFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType); +AQHOME_API AQH_DEVICE *AQH_DataIpc_ReadDeviceFromTagList(const GWEN_TAG16_LIST *tagList, unsigned int wantedTagType); + #endif diff --git a/aqhome/ipc/data/msg_data_devices.c b/aqhome/ipc/data/msg_data_devices.c new file mode 100644 index 0000000..16e795e --- /dev/null +++ b/aqhome/ipc/data/msg_data_devices.c @@ -0,0 +1,150 @@ +/**************************************************************************** + * 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 +#include + +#include + + +#define AQH_MSGDATA_DEVICES_MINSIZE GWEN_MSGIPC_OFFS_PAYLOAD + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +GWEN_MSG *AQH_DevicesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_DEVICE_LIST *deviceList) +{ + GWEN_MSG *msg; + GWEN_BUFFER *buf; + int rv; + + buf=GWEN_Buffer_new(0, 256, 0, 1); + GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_DEVICES_TAGS_FLAGS, flags, buf); + rv=AQH_DataIpc_WriteDeviceListAsTagsToBuffer(AQH_MSGDATA_DEVICES_TAGS_DEVICE, deviceList, buf); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + GWEN_Buffer_free(buf); + return NULL; + } + + 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; +} + + + +GWEN_MSG *AQH_DevicesDataIpcMsg_newForOneDevice(uint16_t code, uint32_t flags, const AQH_DEVICE *device) +{ + GWEN_MSG *msg; + GWEN_BUFFER *buf; + int rv; + + buf=GWEN_Buffer_new(0, 256, 0, 1); + GWEN_Tag16_WriteUint32TagToBuffer(AQH_MSGDATA_DEVICES_TAGS_FLAGS, flags, buf); + rv=AQH_DataIpc_WriteDeviceAsTagToBuffer(AQH_MSGDATA_DEVICES_TAGS_DEVICE, device, buf); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + GWEN_Buffer_free(buf); + return NULL; + } + + 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_DevicesDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy) +{ + AQH_Tag16IpcMsg_ExtendAndParse(msg, doCopy); +} + + + +AQH_DEVICE_LIST *AQH_DevicesDataIpcMsg_ReadDeviceList(const GWEN_MSG *msg) +{ + const GWEN_TAG16_LIST *tagList; + + tagList=AQH_Tag16IpcMsg_GetTags(msg); + if (tagList) { + AQH_DEVICE_LIST *deviceList; + + deviceList=AQH_DataIpc_ReadDevicesFromTagList(tagList, AQH_MSGDATA_DEVICES_TAGS_DEVICE); + if (deviceList==NULL) { + DBG_INFO(AQH_LOGDOMAIN, "No device list received"); + } + return deviceList; + } + else { + DBG_INFO(AQH_LOGDOMAIN, "No tag16 list received"); + return NULL; + } +} + + + +AQH_DEVICE *AQH_DevicesDataIpcMsg_ReadFirstDevice(const GWEN_MSG *msg) +{ + return AQH_DataIpc_ReadDeviceFromTagList(AQH_Tag16IpcMsg_GetTags(msg), AQH_MSGDATA_DEVICES_TAGS_DEVICE); +} + + + + +uint32_t AQH_DevicesDataIpcMsg_GetFlags(const GWEN_MSG *msg) +{ + return AQH_Tag16IpcMsg_GetTagDataAsUint32(msg, AQH_MSGDATA_DEVICES_TAGS_FLAGS, 0); +} + + + +void AQH_DevicesDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText) +{ + if (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSGDATA_DEVICES_MINSIZE) { + GWEN_Buffer_AppendArgs(dbuf, + "DEVICES (code=%d, proto=%d, proto version=%d, flags=0x%08x)\n", + GWEN_IpcMsg_GetCode(msg), + GWEN_IpcMsg_GetProtoId(msg), + GWEN_IpcMsg_GetProtoVersion(msg), + (unsigned int)AQH_DevicesDataIpcMsg_GetFlags(msg)); + } +} + + + + + + diff --git a/aqhome/ipc/data/msg_data_devices.h b/aqhome/ipc/data/msg_data_devices.h new file mode 100644 index 0000000..377dfa0 --- /dev/null +++ b/aqhome/ipc/data/msg_data_devices.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * 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_DEVICES_H +#define AQH_MSG_IPC_DATA_DEVICES_H + + +#include + +#include + +#include + + +/** + * This message is used in request AQH_MSGTYPE_IPC_DATA_ADDDEVICES_REQ and in response AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP. + */ + +#define AQH_MSGDATA_DEVICES_FLAGS_LASTMSG 0x0001 + +#define AQH_MSGDATA_DEVICES_TAGS_FLAGS 0x01 +#define AQH_MSGDATA_DEVICES_TAGS_DEVICE 0xc2 + + +AQHOME_API GWEN_MSG *AQH_DevicesDataIpcMsg_new(uint16_t code, uint32_t flags, const AQH_DEVICE_LIST *deviceList); +AQHOME_API GWEN_MSG *AQH_DevicesDataIpcMsg_newForOneDevice(uint16_t code, uint32_t flags, const AQH_DEVICE *device); + +AQHOME_API void AQH_DevicesDataIpcMsg_Parse(GWEN_MSG *msg, int doCopy); + +AQHOME_API AQH_DEVICE_LIST *AQH_DevicesDataIpcMsg_ReadDeviceList(const GWEN_MSG *msg); +AQHOME_API AQH_DEVICE *AQH_DevicesDataIpcMsg_ReadFirstDevice(const GWEN_MSG *msg); + + +AQHOME_API uint32_t AQH_DevicesDataIpcMsg_GetFlags(const GWEN_MSG *msg); + +AQHOME_API void AQH_DevicesDataIpcMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText); + + + + + + + +#endif + + + diff --git a/aqhome/ipc/endpoint_ipc.h b/aqhome/ipc/endpoint_ipc.h index 4da5625..f2f52da 100644 --- a/aqhome/ipc/endpoint_ipc.h +++ b/aqhome/ipc/endpoint_ipc.h @@ -17,14 +17,19 @@ #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_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 -#define AQH_IPCENDPOINT_PERMS_SETDATA 0x0080 +#define AQH_IPCENDPOINT_PERMS_LISTDATA 0x0010 +#define AQH_IPCENDPOINT_PERMS_READDATA 0x0020 +#define AQH_IPCENDPOINT_PERMS_ADDDATA 0x0040 +#define AQH_IPCENDPOINT_PERMS_SETDATA 0x0080 + +#define AQH_IPCENDPOINT_PERMS_LISTDEVICES 0x0100 +#define AQH_IPCENDPOINT_PERMS_READDEVICE 0x0200 +#define AQH_IPCENDPOINT_PERMS_ADDDEVICE 0x0400 +#define AQH_IPCENDPOINT_PERMS_MODDEVICE 0x0800