adapted to latest changes in gwen, more work on data and nodes servers.
This commit is contained in:
396
apps/aqhome-nodes/devicesread.c
Normal file
396
apps/aqhome-nodes/devicesread.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 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 "./devicesread.h"
|
||||
#include "./aqhomed_p.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
|
||||
#include <gwenhywfar/directory.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/stringlist.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _readDeviceFileToList(const char *sFilename, AQHNODE_DEVICE_LIST *deviceList);
|
||||
static AQHNODE_DEVICE_LIST *_readDeviceFiles(const GWEN_STRINGLIST *sl);
|
||||
static int _readXmlDevices(GWEN_XMLNODE *deviceListNode, AQHNODE_DEVICE_LIST *deviceList);
|
||||
static AQHNODE_DEVICE *_readXmlDevice(GWEN_XMLNODE *deviceNode);
|
||||
static AQHNODE_VALUE_LIST *_readXmlValueList(GWEN_XMLNODE *valuesNode);
|
||||
static AQHNODE_VALUE *_readXmlValue(GWEN_XMLNODE *valueNode);
|
||||
static int _readManufacturer(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode);
|
||||
static int _readDeviceType(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode);
|
||||
static int _readDeviceVersion(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQHNODE_DEVICE_LIST *AqHomeNodes_ReadDeviceFile(const char *sFilename)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=GWEN_Directory_GetPath(sFilename, GWEN_PATH_FLAGS_CHECKROOT | GWEN_PATH_FLAGS_PATHMUSTEXIST | GWEN_PATH_FLAGS_VARIABLE);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "File \"%s\" does not exists, writing later", sFilename);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
AQHNODE_DEVICE_LIST *deviceList;
|
||||
|
||||
deviceList=AQHNODE_Device_List_new();
|
||||
rv=_readDeviceFileToList(sFilename, deviceList);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "File \"%s\" not found", sFilename);
|
||||
AQHNODE_Device_List_free(deviceList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (AQHNODE_Device_List_GetCount(deviceList)<1) {
|
||||
AQHNODE_Device_List_free(deviceList);
|
||||
return NULL;
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHNODE_DEVICE_LIST *AqHomeNodes_ReadDataDeviceFiles()
|
||||
{
|
||||
GWEN_STRINGLIST *sl;
|
||||
|
||||
sl=AQH_GetListOfMatchingDataFiles("aqhome/devices/nodes", "*.xml");
|
||||
if (sl) {
|
||||
AQHNODE_DEVICE_LIST *deviceList;
|
||||
|
||||
deviceList=_readDeviceFiles(sl);
|
||||
GWEN_StringList_free(sl);
|
||||
if (deviceList==NULL) {
|
||||
DBG_INFO(NULL, "Error reading data device files");
|
||||
return NULL;
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No data device files");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHNODE_DEVICE_LIST *_readDeviceFiles(const GWEN_STRINGLIST *sl)
|
||||
{
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
AQHNODE_DEVICE_LIST *deviceList;
|
||||
|
||||
deviceList=AQHNODE_Device_List_new();
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se) {
|
||||
const char *s;
|
||||
|
||||
s=GWEN_StringListEntry_Data(se);
|
||||
if (s && *s) {
|
||||
int rv;
|
||||
|
||||
DBG_INFO(NULL, "Reading device file \"%s\"", s);
|
||||
rv=_readDeviceFileToList(s, deviceList);
|
||||
if (rv<0 && rv!=GWEN_ERROR_NO_DATA) {
|
||||
DBG_WARN(NULL, "Error reading device file \"%s\" (%d), ignoring", s, rv);
|
||||
}
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
|
||||
if (AQHNODE_Device_List_GetCount(deviceList)<1) {
|
||||
AQHNODE_Device_List_free(deviceList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readDeviceFileToList(const char *sFilename, AQHNODE_DEVICE_LIST *deviceList)
|
||||
{
|
||||
GWEN_XMLNODE *rootNode;
|
||||
GWEN_XMLNODE *deviceListNode;
|
||||
int rv;
|
||||
|
||||
rootNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, NULL);
|
||||
rv=GWEN_XML_ReadFile(rootNode, sFilename, GWEN_XML_FLAGS_DEFAULT);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading XML file \"%s\": %d", sFilename, rv);
|
||||
GWEN_XMLNode_free(rootNode);
|
||||
return rv;
|
||||
}
|
||||
|
||||
deviceListNode=GWEN_XMLNode_FindFirstTag(rootNode, "devices", NULL, NULL);
|
||||
if (deviceListNode==NULL)
|
||||
deviceListNode=rootNode;
|
||||
|
||||
rv=_readXmlDevices(deviceListNode, deviceList);
|
||||
if (rv<0 && rv!=GWEN_ERROR_NO_DATA) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading devices from file \"%s\" (%d)", sFilename, rv);
|
||||
GWEN_XMLNode_free(rootNode);
|
||||
return rv;
|
||||
}
|
||||
|
||||
GWEN_XMLNode_free(rootNode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readXmlDevices(GWEN_XMLNODE *deviceListNode, AQHNODE_DEVICE_LIST *deviceList)
|
||||
{
|
||||
GWEN_XMLNODE *deviceNode;
|
||||
|
||||
deviceNode=GWEN_XMLNode_FindFirstTag(deviceListNode, "device", NULL, NULL);
|
||||
if (deviceNode) {
|
||||
while(deviceNode) {
|
||||
const char *driverName;
|
||||
|
||||
driverName=GWEN_XMLNode_GetProperty(deviceNode, "driver", NULL);
|
||||
if (driverName && *driverName && strcasecmp(driverName, "nodes")==0) {
|
||||
AQHNODE_DEVICE *device;
|
||||
|
||||
device=_readXmlDevice(deviceNode);
|
||||
if (device==NULL) {
|
||||
DBG_INFO(NULL, "Error reading device from XML");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
else {
|
||||
const char *sDeviceName;
|
||||
|
||||
sDeviceName=AQHNODE_Device_GetName(device);
|
||||
if (sDeviceName && *sDeviceName) {
|
||||
DBG_ERROR(NULL, "Adding device type \"%s\" to list", sDeviceName?sDeviceName:"<no type name>");
|
||||
AQHNODE_Device_List_Add(device, deviceList);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Device with no name, not adding");
|
||||
AQHNODE_Device_free(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Device is not an NODES device, ignoring");
|
||||
}
|
||||
deviceNode=GWEN_XMLNode_FindNextTag(deviceNode, "device", NULL, NULL);
|
||||
} /* while */
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No <device> element found");
|
||||
return GWEN_ERROR_NO_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHNODE_DEVICE *_readXmlDevice(GWEN_XMLNODE *deviceNode)
|
||||
{
|
||||
AQHNODE_DEVICE *device;
|
||||
GWEN_XMLNODE *valuesNode;
|
||||
int rv;
|
||||
|
||||
device=AQHNODE_Device_new();
|
||||
AQHNODE_Device_SetName(device, GWEN_XMLNode_GetProperty(deviceNode, "name", NULL));
|
||||
AQHNODE_Device_SetDriver(device, GWEN_XMLNode_GetProperty(deviceNode, "driver", NULL));
|
||||
rv=_readManufacturer(device, deviceNode);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHNODE_Device_free(device);
|
||||
return NULL;
|
||||
}
|
||||
rv=_readDeviceType(device, deviceNode);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHNODE_Device_free(device);
|
||||
return NULL;
|
||||
}
|
||||
rv=_readDeviceVersion(device, deviceNode);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHNODE_Device_free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read values */
|
||||
valuesNode=GWEN_XMLNode_FindFirstTag(deviceNode, "values", NULL, NULL);
|
||||
if (valuesNode) {
|
||||
AQHNODE_VALUE_LIST *valueList;
|
||||
|
||||
valueList=_readXmlValueList(valuesNode);
|
||||
if (valueList==NULL) {
|
||||
DBG_INFO(NULL, "here");
|
||||
AQHNODE_Device_free(device);
|
||||
return NULL;
|
||||
}
|
||||
AQHNODE_Device_SetValueList(device, valueList);
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No <values> element");
|
||||
AQHNODE_Device_free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHNODE_VALUE_LIST *_readXmlValueList(GWEN_XMLNODE *valuesNode)
|
||||
{
|
||||
AQHNODE_VALUE_LIST *valueList;
|
||||
GWEN_XMLNODE *node;
|
||||
|
||||
valueList=AQHNODE_Value_List_new();
|
||||
node=GWEN_XMLNode_FindFirstTag(valuesNode, "value", NULL, NULL);
|
||||
while(node) {
|
||||
AQHNODE_VALUE *value;
|
||||
|
||||
value=_readXmlValue(node);
|
||||
if (value)
|
||||
AQHNODE_Value_List_Add(value, valueList);
|
||||
else {
|
||||
DBG_INFO(NULL, "Error reading <value> element");
|
||||
AQHNODE_Value_List_free(valueList);
|
||||
return NULL;
|
||||
}
|
||||
node=GWEN_XMLNode_FindNextTag(node, "value", NULL, NULL);
|
||||
}
|
||||
if (AQHNODE_Value_List_GetCount(valueList)<1) {
|
||||
DBG_INFO(NULL, "No <value> element in <values> element");
|
||||
AQHNODE_Value_List_free(valueList);
|
||||
return NULL;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHNODE_VALUE *_readXmlValue(GWEN_XMLNODE *valueNode)
|
||||
{
|
||||
AQHNODE_VALUE *value;
|
||||
|
||||
value=AQHNODE_Value_new();
|
||||
AQHNODE_Value_SetName(value, GWEN_XMLNode_GetProperty(valueNode, "name", NULL));
|
||||
AQHNODE_Value_SetId(value, GWEN_XMLNode_GetIntProperty(valueNode, "id", 0));
|
||||
AQHNODE_Value_SetValueUnits(value, GWEN_XMLNode_GetProperty(valueNode, "units", NULL));
|
||||
AQHNODE_Value_SetValueType(value, AQH_ValueType_fromString(GWEN_XMLNode_GetProperty(valueNode, "type", NULL)));
|
||||
AQHNODE_Value_SetDataType(value, AQH_ValueDataType_fromString(GWEN_XMLNode_GetProperty(valueNode, "dataType", NULL)));
|
||||
AQHNODE_Value_SetModality(value, AQH_ValueModality_fromString(GWEN_XMLNode_GetProperty(valueNode, "modality", NULL)));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readManufacturer(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode)
|
||||
{
|
||||
const char *s;
|
||||
uint32_t v;
|
||||
|
||||
s=GWEN_XMLNode_GetCharValue(deviceNode, "manufacturer", NULL);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(NULL, "Missing manufacturer");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
if (strlen(s)>4) {
|
||||
DBG_ERROR(NULL, "Bad manufacturer string (too long): \"%s\"", s);
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
v=0;
|
||||
while(*s) {
|
||||
v<<=8;
|
||||
v|=*s & 0xff;
|
||||
s++;
|
||||
}
|
||||
v=((v>>24) & 0x000000ffL) |
|
||||
((v>>8) & 0x0000ff00L) |
|
||||
((v<<8) & 0x00ff0000L) |
|
||||
((v<<24) & 0xff000000L);
|
||||
|
||||
AQHNODE_Device_SetManufacturer(device, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readDeviceType(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode)
|
||||
{
|
||||
const char *s;
|
||||
uint16_t v;
|
||||
|
||||
s=GWEN_XMLNode_GetCharValue(deviceNode, "devicetype", NULL);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(NULL, "Missing device type");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
if (strlen(s)>2) {
|
||||
DBG_ERROR(NULL, "Bad devicetype string (too long): \"%s\"", s);
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
v=0;
|
||||
while(*s) {
|
||||
v<<=8;
|
||||
v|=*s & 0xff;
|
||||
s++;
|
||||
}
|
||||
|
||||
AQHNODE_Device_SetDeviceType(device, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readDeviceVersion(AQHNODE_DEVICE *device, GWEN_XMLNODE *deviceNode)
|
||||
{
|
||||
int v;
|
||||
|
||||
v=GWEN_XMLNode_GetIntValue(deviceNode, "deviceversion", -1);
|
||||
if (v<0) {
|
||||
DBG_ERROR(NULL, "Missing device version");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
AQHNODE_Device_SetDeviceVersion(device, v<<8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user