From 487e506a01baa3dae6f08b3d58e233f69a3ea8be Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Thu, 10 Aug 2023 19:28:10 +0200 Subject: [PATCH] added urlhandler for devices. --- apps/aqhome-storage/0BUILD | 2 + apps/aqhome-storage/init_http.c | 21 ++ apps/aqhome-storage/u_devices.c | 338 ++++++++++++++++++++++++++++++++ apps/aqhome-storage/u_devices.h | 23 +++ aqhome/data/device.t2d | 6 +- aqhome/data/storage.c | 7 + aqhome/data/storage.h | 1 + 7 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 apps/aqhome-storage/u_devices.c create mode 100644 apps/aqhome-storage/u_devices.h diff --git a/apps/aqhome-storage/0BUILD b/apps/aqhome-storage/0BUILD index 995a96d..99d9280 100644 --- a/apps/aqhome-storage/0BUILD +++ b/apps/aqhome-storage/0BUILD @@ -48,6 +48,7 @@ u_objects.h u_objects_p.h u_rooms.h + u_devices.h u_static.h u_static_p.h aqhomehttp.h @@ -68,6 +69,7 @@ u_login.c u_objects.c u_rooms.c + u_devices.c u_static.c main.c aqhomehttp.c diff --git a/apps/aqhome-storage/init_http.c b/apps/aqhome-storage/init_http.c index 5f38309..1fbb070 100644 --- a/apps/aqhome-storage/init_http.c +++ b/apps/aqhome-storage/init_http.c @@ -16,6 +16,7 @@ #include "./aqhomehttp.h" #include "./u_login.h" #include "./u_rooms.h" +#include "./u_devices.h" #include "./u_static.h" #include "aqhome/msg/endpoint_tty.h" @@ -73,6 +74,7 @@ static GWEN_MSG_ENDPOINT *_acceptHttpFn(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, static int _createUrlHandler_login(AQHOME_STORAGE *aqh); static int _createUrlHandler_rooms(AQHOME_STORAGE *aqh); +static int _createUrlHandler_devices(AQHOME_STORAGE *aqh); static int _createUrlHandler_static(AQHOME_STORAGE *aqh); @@ -118,6 +120,12 @@ int AqHomeStorage_SetupHttp(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs) return rv; } + rv=_createUrlHandler_devices(aqh); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + return rv; + } + rv=_createUrlHandler_static(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); @@ -249,6 +257,19 @@ int _createUrlHandler_rooms(AQHOME_STORAGE *aqh) +int _createUrlHandler_devices(AQHOME_STORAGE *aqh) +{ + AQH_HTTP_URLHANDLER *uh; + + uh=AQH_DevicesHttpUrlHandler_new(aqh->httpService); + AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); + AQH_HttpUrlHandler_AddUrlPattern(uh, "/devices/*"); + AQH_HttpService_AddUrlHandler(aqh->httpService, uh); + return 0; +} + + + int _createUrlHandler_static(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; diff --git a/apps/aqhome-storage/u_devices.c b/apps/aqhome-storage/u_devices.c new file mode 100644 index 0000000..1ade1e8 --- /dev/null +++ b/apps/aqhome-storage/u_devices.c @@ -0,0 +1,338 @@ +/**************************************************************************** + * 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 "./u_devices.h" +#include "./u_objects.h" +#include "./aqhomehttp.h" + +#include +#include +#include + + + +/* ------------------------------------------------------------------------------------------------ + * defines + * ------------------------------------------------------------------------------------------------ + */ + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id); +static GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id); +static int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf); + +static void _writeEditingTable(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static void _setFromObject(AQH_DEVICE *device, const AQH_DEVICE *srcDevice); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +AQH_HTTP_URLHANDLER *AQH_DevicesHttpUrlHandler_new(AQH_SERVICE *sv) +{ + AQH_HTTP_URLHANDLER *uh; + + uh=AQH_ObjectsHttpUrlHandler_new(sv, + AQHOME_HTTP_PERMS_LIST_DEVICES, + AQHOME_HTTP_PERMS_ADD_DEVICE, + AQHOME_HTTP_PERMS_DEL_DEVICE, + AQHOME_HTTP_PERMS_EDIT_DEVICE, + "/devices/list"); + AQH_ObjectsHttpUrlHandler_SetAddOrEditObjectFn(uh, _addOrEditObject); + AQH_ObjectsHttpUrlHandler_SetFindObjectByIdAndReturnAsDbFn(uh, _findObjectByIdAndReturnAsDb); + AQH_ObjectsHttpUrlHandler_SetWriteAddPageFn(uh, _writeAddPage); + AQH_ObjectsHttpUrlHandler_SetWriteEditPageFn(uh, _writeEditPage); + AQH_ObjectsHttpUrlHandler_SetListObjectsIntoBufferFn(uh, _listObjectsIntoBuffer); + + return uh; +} + + + +int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + AQH_DEVICE *newDevice; + const char *deviceName; + int rv; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + + newDevice=AQH_Device_fromDb(db); + + deviceName=AQH_Device_GetName(newDevice); + if (!(deviceName && *deviceName)) { + DBG_INFO(NULL, "Missing device name"); + AQH_Device_free(newDevice); + return GWEN_ERROR_INVALID; + } + + rv=AqHomeHttpService_LockStorage(sv); + if (rv<0) { + DBG_ERROR(NULL, "Error locking storage"); + AQH_Device_free(newDevice); + return GWEN_ERROR_IO; + } + + if (id>0) { + AQH_DEVICE *device; + + DBG_INFO(NULL, "Edit existing device"); + device=AQH_Storage_GetDeviceById(sto, id); + if (device==NULL) { + AqHomeHttpService_UnlockStorage(sv); + DBG_ERROR(NULL, "Device %d not found", id); + AQH_Device_free(newDevice); + return GWEN_ERROR_NOT_FOUND; + } + AQH_Device_SetId(device, id); + _setFromObject(device, newDevice); + AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); + } + else { + AQH_DEVICE *device; + + DBG_INFO(NULL, "Adding new device"); + device=AQH_Storage_GetDeviceByName(sto, deviceName); + if (device) { + AqHomeHttpService_UnlockStorage(sv); + DBG_ERROR(NULL, "Device %s exists", deviceName); + AQH_Device_free(newDevice); + return GWEN_ERROR_FOUND; + } + device=AQH_Device_new(); + AQH_Device_SetId(device, 0); + _setFromObject(device, newDevice); + AQH_Storage_AddDevice(sto, device); + AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); + } + AQH_Device_free(newDevice); + + rv=AqHomeHttpService_UnlockStorage(sv); + if (rv<0) { + DBG_ERROR(NULL, "Error unlocking storage"); + return GWEN_ERROR_IO; + } + return 0; +} + + + +void _setFromObject(AQH_DEVICE *device, const AQH_DEVICE *srcDevice) +{ + AQH_Device_SetRoomId(device, AQH_Device_GetRoomId(srcDevice)); + AQH_Device_SetName(device, AQH_Device_GetName(srcDevice)); + AQH_Device_SetLocation(device, AQH_Device_GetLocation(srcDevice)); + AQH_Device_SetDescription(device, AQH_Device_GetDescription(srcDevice)); +} + + + +GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + const AQH_DEVICE *device; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + + device=AQH_Storage_GetDeviceById(sto, id); + if (device) { + GWEN_DB_NODE *db; + + db=GWEN_DB_Group_new("device"); + AQH_Device_toDb(device, db); + return db; + } + return NULL; +} + + + +int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + GWEN_Buffer_AppendArgs(pageBuf, + "

%s


\n" + "
", + I18N("Add Device")); + _writeEditingTable(uh, dbValues, pageBuf); + GWEN_Buffer_AppendArgs(pageBuf, "
", I18N("Submit")); + return 0; +} + + + +int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + + GWEN_Buffer_AppendArgs(pageBuf, + "

%s


\n" + "
", + I18N("Edit Device"), + (long unsigned int)(dbValues?GWEN_DB_GetIntValue(dbValues, "id", 0, 0):0)); + _writeEditingTable(uh, dbValues, pageBuf); + GWEN_Buffer_AppendArgs(pageBuf, "
", I18N("Submit")); + return 0; +} + + + +void _writeEditingTable(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + const AQH_ROOM_LIST *roomList; + unsigned long int selectedRoomId=0; + char numbuf[16]; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + roomList=AQH_Storage_GetRoomList(sto); + + selectedRoomId=(unsigned long int)(dbValues?GWEN_DB_GetIntValue(dbValues, "roomId", 0, 0):0); + snprintf(numbuf, sizeof(numbuf)-1, "%lu", selectedRoomId); + numbuf[sizeof(numbuf)-1]=0; + + GWEN_Buffer_AppendArgs(pageBuf, + " " + " " + " " + " " + " ", + I18N("Name"), + dbValues?GWEN_DB_GetCharValue(dbValues, "name", 0, ""):""); + GWEN_Buffer_AppendArgs(pageBuf, + "" + ""); + + GWEN_Buffer_AppendArgs(pageBuf, + " " + " " + " " + " " + " " + " " + " " + " " + "
", + I18N("Location"), + dbValues?GWEN_DB_GetCharValue(dbValues, "location", 0, ""):"", + I18N("Description"), + dbValues?GWEN_DB_GetCharValue(dbValues, "description", 0, ""):""); +} + + + +void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + const AQH_DEVICE_LIST *rl; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + + GWEN_Buffer_AppendArgs(pageBuf, + "

%s

" + "" + "" + " " + "", + I18N("Devices"), + I18N("Name"), + I18N("Room"), + I18N("Location"), + I18N("Description")); + GWEN_Buffer_AppendString(pageBuf, ""); + rl=AQH_Storage_GetDeviceList(sto); + if (rl) { + const AQH_DEVICE *device; + + device=AQH_Device_List_First(rl); + while(device) { + long unsigned int id; + int roomId; + const char *name; + const char *roomName=NULL; + const char *descr; + const char *location; + const AQH_ROOM *r=NULL; + + id=(long unsigned int) AQH_Device_GetId(device); + roomId=(long unsigned int) AQH_Device_GetRoomId(device); + if (roomId>0) + r=AQH_Storage_GetRoomById(sto, roomId); + if (r) + roomName=AQH_Room_GetName(r); + + name=AQH_Device_GetName(device); + descr=AQH_Device_GetDescription(device); + location=AQH_Device_GetLocation(device); + GWEN_Buffer_AppendArgs(pageBuf, + "" + "" + "", + name?name:"", + roomName?roomName:"", + location?location:"", + descr?descr:"", id); + + device=AQH_Device_List_Next(device); + } + } + GWEN_Buffer_AppendString(pageBuf, ""); + GWEN_Buffer_AppendArgs(pageBuf, "
%s%s%s%s
%s%s%s%s" + "
%s
", I18N("Add Device")); +} + + + + + diff --git a/apps/aqhome-storage/u_devices.h b/apps/aqhome-storage/u_devices.h new file mode 100644 index 0000000..d5e444c --- /dev/null +++ b/apps/aqhome-storage/u_devices.h @@ -0,0 +1,23 @@ +/**************************************************************************** + * 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_STORAGE_U_DEVICES_H +#define AQHOME_STORAGE_U_DEVICES_H + + +#include "aqhome/http/urlhandler.h" + + + +AQH_HTTP_URLHANDLER *AQH_DevicesHttpUrlHandler_new(AQH_SERVICE *sv); + + + +#endif + + diff --git a/aqhome/data/device.t2d b/aqhome/data/device.t2d index 11ec699..352f22e 100644 --- a/aqhome/data/device.t2d +++ b/aqhome/data/device.t2d @@ -48,21 +48,21 @@ 0 0 public - + own with_getbymember 0 0 public - + own 0 0 public - + own diff --git a/aqhome/data/storage.c b/aqhome/data/storage.c index 59423b3..201d763 100644 --- a/aqhome/data/storage.c +++ b/aqhome/data/storage.c @@ -143,6 +143,13 @@ AQH_DEVICE *AQH_Storage_GetDeviceById(const AQH_STORAGE *sto, uint64_t id) +AQH_DEVICE *AQH_Storage_GetDeviceByName(const AQH_STORAGE *sto, const char *s) +{ + return sto?AQH_Device_List_GetByName(sto->deviceList, s):NULL; +} + + + void AQH_Storage_AddMqttTopic(AQH_STORAGE *sto, AQH_MQTT_TOPIC *t) { if (sto && t) { diff --git a/aqhome/data/storage.h b/aqhome/data/storage.h index a2b0576..fb605c5 100644 --- a/aqhome/data/storage.h +++ b/aqhome/data/storage.h @@ -57,6 +57,7 @@ AQHOME_API AQH_ROOM *AQH_Storage_GetRoomByName(const AQH_STORAGE *sto, const cha AQHOME_API void AQH_Storage_AddDevice(AQH_STORAGE *sto, AQH_DEVICE *dev); 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_GetDeviceByName(const AQH_STORAGE *sto, const char *s); AQHOME_API void AQH_Storage_AddMqttTopic(AQH_STORAGE *sto, AQH_MQTT_TOPIC *t); AQHOME_API AQH_MQTT_TOPIC_LIST *AQH_Storage_GetMqttTopicList(const AQH_STORAGE *sto);