From eb27d223fb187c177617dd620bc036ae4df50585 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 6 Sep 2025 00:37:39 +0200 Subject: [PATCH] aqhome-tool: added command "devicestate". --- apps/aqhome-tool/data/0BUILD | 2 + apps/aqhome-tool/data/devicestate.c | 260 ++++++++++++++++++++++++++++ apps/aqhome-tool/data/devicestate.h | 21 +++ apps/aqhome-tool/main.c | 2 + 4 files changed, 285 insertions(+) create mode 100644 apps/aqhome-tool/data/devicestate.c create mode 100644 apps/aqhome-tool/data/devicestate.h diff --git a/apps/aqhome-tool/data/0BUILD b/apps/aqhome-tool/data/0BUILD index 359c2f9..ed2824c 100644 --- a/apps/aqhome-tool/data/0BUILD +++ b/apps/aqhome-tool/data/0BUILD @@ -43,6 +43,7 @@ setdata.h moddevice.h watch.h + devicestate.h @@ -58,6 +59,7 @@ setdata.c moddevice.c watch.c + devicestate.c diff --git a/apps/aqhome-tool/data/devicestate.c b/apps/aqhome-tool/data/devicestate.c new file mode 100644 index 0000000..c6f9dcb --- /dev/null +++ b/apps/aqhome-tool/data/devicestate.c @@ -0,0 +1,260 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2025 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "./devicestate.h" +#include "../utils.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" +#include "aqhome/msg/ipc/m_ipc.h" +#include "aqhome/msg/ipc/m_ipc_result.h" +#include "aqhome/msg/ipc/data/m_ipcd.h" +#include "aqhome/msg/ipc/data/m_ipcd_getdata.h" +#include "aqhome/msg/ipc/data/m_ipcd_multidata.h" +#include "aqhome/dataclient/client.h" + +#include +#include +#include +#include +#include + +#include + + + +/* ------------------------------------------------------------------------------------------------ + * defs + * ------------------------------------------------------------------------------------------------ + */ + +#define I18S(msg) msg +#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg) + +#define A_ARG GWEN_ARGS_FLAGS_HAS_ARGUMENT +#define A_END (GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST) +#define A_CHAR GWEN_ArgsType_Char +#define A_INT GWEN_ArgsType_Int + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static int _runCommand(AQH_DATACLIENT *dc); +static void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device); +static void _handleValue(AQH_DATACLIENT *dc, const AQH_DEVICE *device, const AQH_VALUE *value); +static void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues); +static void _printSingleDataPoint(uint64_t timestamp, double data); + + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv) +{ + AQH_EVENT_LOOP *eventLoop; + AQH_DATACLIENT *dc; + int rv; + const GWEN_ARGS args[]= { + /* flags type name min max s long short_descr, long_descr */ + { A_ARG, A_CHAR, "brokerAddress", 0, 1, "t", "tcpaddress", I18S("TCP address to connect to [127.0.0.1]"), NULL}, + { A_ARG, A_INT, "brokerPort", 0, 1, "P", "tcpport", I18S("Specify the TCP port to listen on"), NULL}, + { A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL}, + { A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL}, + { A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL}, + { A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL}, + { A_ARG, A_CHAR, "device", 1, 1, "d", "device", I18S("device name"), NULL}, + { A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL}, + { A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL} + }; + + eventLoop=AQH_EventLoop_new(); + dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION); + + rv=AQH_DataClient_ReadLocalArgs(dc, dbGlobalArgs, args, argc, argv); + if (rv<0) { + DBG_ERROR(NULL, "here (%d)", rv); + AQH_DataClient_free(dc); + AQH_EventLoop_free(eventLoop); + return 2; + } + + rv=AQH_DataClient_ConnectWithArgs(dc, 0); + if (rv<0) { + DBG_ERROR(NULL, "Error connecting (%d)", rv); + AQH_DataClient_free(dc); + AQH_EventLoop_free(eventLoop); + return 2; + } + + rv=_runCommand(dc); + if (rv<0) { + DBG_ERROR(NULL, "Error running (%d)", rv); + AQH_DataClient_free(dc); + AQH_EventLoop_free(eventLoop); + return 2; + } + + AQH_DataClient_free(dc); + AQH_EventLoop_free(eventLoop); + return 0; +} + + + +int _runCommand(AQH_DATACLIENT *dc) +{ + GWEN_DB_NODE *dbLocalArgs; + const char *deviceName; + AQH_DEVICE_LIST *deviceList; + AQH_DEVICE *device; + + dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc); + deviceName=GWEN_DB_GetCharValue(dbLocalArgs, "device", 0, "*"); + + deviceList=AQH_DataClient_GetDevices(dc); + if (deviceList==NULL) { + DBG_ERROR(NULL, "Error getting devices"); + return GWEN_ERROR_GENERIC; + } + + device=AQH_Device_List_First(deviceList); + while(device) { + const char *s; + + s=AQH_Device_GetNameForSystem(device); + if (s && *s && -1!=GWEN_Text_ComparePattern(s, deviceName, 0)) { + _handleDevice(dc, device); + } + + device=AQH_Device_List_Next(device); + } + + AQH_Device_List_free(deviceList); + + return 0; +} + + + +void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device) +{ + AQH_VALUE_LIST *valueList; + const char *devName; + const char *roomName; + const char *location; + const char *descr; + + devName=AQH_Device_GetNameForSystem(device); + roomName=AQH_Device_GetRoomName(device); + location=AQH_Device_GetLocation(device); + descr=AQH_Device_GetDescription(device); + + fprintf(stdout, "%s (room: %s, loc: %s, descr: %s)\n", + devName, + roomName?roomName:"--", + location?location:"--", + descr?descr:"--"); + valueList=AQH_DataClient_GetValues(dc, devName, 0); + if (valueList) { + const AQH_VALUE *value; + + value=AQH_Value_List_First(valueList); + while(value) { + if (AQH_Value_GetValueType(value)==AQH_ValueType_Sensor) + _handleValue(dc, device, value); + value=AQH_Value_List_Next(value); + } + } + + AQH_Value_List_free(valueList); +} + + + +void _handleValue(AQH_DATACLIENT *dc, const AQH_DEVICE *device, const AQH_VALUE *value) +{ + GWEN_DB_NODE *dbLocalArgs; + const char *valueName; + int numDataPoints; + + dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc); + numDataPoints=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 5); + + valueName=AQH_Value_GetName(value); + if (valueName && -1==GWEN_Text_ComparePattern(valueName, "stats_*", 0)) { + const char *valueNameForSystem; + uint64_t *dataPoints; + uint64_t recvdNum; + + valueNameForSystem=AQH_Value_GetNameForSystem(value); + fprintf(stdout, " %s: ", valueName?valueName:""); + + dataPoints=malloc(numDataPoints*sizeof(uint64_t)*2); + + recvdNum=AQH_DataClient_GetLastData(dc, valueNameForSystem, dataPoints, numDataPoints); + if (recvdNum>0) + _printDataPoints(dataPoints, recvdNum); + + free(dataPoints); + fprintf(stdout, "\n"); + } +} + + + +void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues) +{ + uint32_t i; + + for(i=0; i + + + +int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv); + + +#endif + diff --git a/apps/aqhome-tool/main.c b/apps/aqhome-tool/main.c index a13cb83..ba251fe 100644 --- a/apps/aqhome-tool/main.c +++ b/apps/aqhome-tool/main.c @@ -23,6 +23,7 @@ #include "./data/setdata.h" #include "./data/moddevice.h" #include "./data/watch.h" +#include "./data/devicestate.h" #include #include @@ -101,6 +102,7 @@ int main(int argc, char **argv) GWEN_FE_DAH("setdata", AQH_Tool_SetData, I18N("Set data for a value on the data server (e.g. a switch or thermostat)")), GWEN_FE_DAH("moddevice", AQH_Tool_ModDevice, I18N("Modify a device on the data server")), GWEN_FE_DAH("watch", AQH_Tool_Watch, I18N("Watch and print changes of values on the data server")), + GWEN_FE_DAH("devicestate", AQH_Tool_DeviceState, I18N("Show state of devices")), GWEN_FE_END(), }; const GWEN_FUNCS *func;