Files
aqhomecontrol/apps/aqhome-tool/data/adddata.c
Martin Preuss 17d4ce5125 Change AQH_Value field NameForDriver to Name and make it only contain the value name.
Previously this field contained the device name, too. This would make it
necessary for drivers to remove the device part of the name when SetValue
is called. Instead the device name is now always provided by the driver in
the appropriate field DeviceNameForDriver.
2023-10-03 13:31:05 +02:00

314 lines
9.7 KiB
C

/****************************************************************************
* 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 "./adddata.h"
#include "../utils.h"
#include "aqhome/msg/msg_node.h"
#include "aqhome/ipc/msg_ipc_result.h"
#include "aqhome/ipc/data/msg_data_multidata.h"
#include "aqhome/ipc/data/ipc_data.h"
#include <gwenhywfar/args.h>
#include <gwenhywfar/i18n.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
#include <time.h>
#include <unistd.h>
#define I18S(msg) msg
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
static int _doAddData(GWEN_DB_NODE *dbArgs);
static void _sendCommand(GWEN_MSG_ENDPOINT *epTcp, const char *valueName, const char *valueUnits,
uint64_t timestampToSend, double dataToSend);
int AQH_Tool_AddDataPoint(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 */
"valueName", /* name */
1, /* minnum */
1, /* maxnum */
"N", /* short option */
"valuename", /* long option */
I18S("Name/path of the value to add (e.g. server/temp/system)"),
I18S("Name/path of the value to add (e.g. server/temp/system)")
},
{
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
GWEN_ArgsType_Char, /* type */
"valueUnits", /* name */
0, /* minnum */
1, /* maxnum */
"U", /* short option */
"valueunits", /* long option */
I18S("Units of the value to add (e.g. \"Grad Celsius\")"),
I18S("Units of the value to add (e.g. \"Grad Celsius\")")
},
{
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
GWEN_ArgsType_Char, /* type */
"timestamp", /* name */
0, /* minnum */
1, /* maxnum */
"t", /* short option */
"timestamp", /* long option */
I18S("Timestamp of the data (now if omitted)"),
I18S("Timestamp of the data (now if omitted)")
},
{
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
GWEN_ArgsType_Char, /* type */
"value", /* name */
1, /* minnum */
1, /* maxnum */
"v", /* short option */
"value", /* long option */
I18S("Value to write"),
I18S("Value to write")
},
{
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 _doAddData(dbLocalArgs);
}
int _doAddData(GWEN_DB_NODE *dbArgs)
{
GWEN_MSG_ENDPOINT *epTcp;
int timeoutInSeconds;
const char *valueName;
const char *valueUnits;
const char *valueTimestamp;
const char *valueData;
uint64_t timestampToSend;
double dataToSend;
GWEN_MSG *msg;
int rv;
timeoutInSeconds=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 5);
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
valueUnits=GWEN_DB_GetCharValue(dbArgs, "valueUnits", 0, NULL);
valueTimestamp=GWEN_DB_GetCharValue(dbArgs, "timestamp", 0, NULL);
valueData=GWEN_DB_GetCharValue(dbArgs, "value", 0, NULL);
if (!(valueName && *valueName)) {
DBG_ERROR(NULL, "ERROR: Missing value name");
return 1;
}
if (!(valueData && *valueData)) {
DBG_ERROR(NULL, "ERROR: Missing data");
return 1;
}
if (valueTimestamp && *valueTimestamp) {
unsigned long int x;
if (1!=sscanf("%lu", valueTimestamp, &x)) {
DBG_ERROR(NULL, "ERROR: Invalid timestamp");
return 1;
}
timestampToSend=(uint64_t) x;
}
else
timestampToSend=(uint64_t) time(NULL);
rv=GWEN_Text_StringToDouble(valueData, &dataToSend);
if (rv<0) {
DBG_ERROR(NULL, "ERROR: Invalid data");
return 1;
}
/*fprintf(stdout, "Sending AddData request\n");*/
epTcp=Utils_OpenConnection(dbArgs, 0, timeoutInSeconds);
if (epTcp==NULL) {
DBG_ERROR(NULL, "ERROR creating TCP connection");
return 2;
}
_sendCommand(epTcp, valueName, valueUnits, timestampToSend, dataToSend);
for (;;) {
uint16_t code;
msg=Utils_WaitForSpecificIpcMessage(epTcp, AQH_MSGTYPE_IPC_DATA_RESULT, timeoutInSeconds);
if (msg==NULL) {
DBG_ERROR(NULL, "No response received");
return 2;
}
code=GWEN_IpcMsg_GetCode(msg);
if (code==AQH_MSGTYPE_IPC_DATA_RESULT) {
uint32_t resultCode;
resultCode=AQH_ResultIpcMsg_GetResultCode(msg);
if (resultCode!=AQH_MSG_IPC_SUCCESS) {
fprintf(stderr, "ERROR: %d\n", resultCode);
GWEN_MsgEndpoint_free(epTcp);
return 3;
}
else {
fprintf(stdout, "Data added.\n");
break;
}
}
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, const char *valueName, const char *valueUnits, uint64_t timestampToSend, double dataToSend)
{
GWEN_MSG *msgOut;
union {double f; uint64_t i;} u;
uint64_t arrayToSend[2];
AQH_VALUE *value;
u.f=dataToSend;
arrayToSend[0]=timestampToSend;
arrayToSend[1]=u.i;
value=AQH_Value_new();
AQH_Value_SetName(value, valueName);
AQH_Value_SetValueUnits(value, valueUnits);
msgOut=AQH_MultiDataDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, value, arrayToSend, 1);
AQH_Value_free(value);
GWEN_MsgEndpoint_AddSendMessage(epTcp, msgOut);
}