/**************************************************************************** * 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_mqtttopics.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_MQTT_TOPIC *mqttTopic, const AQH_MQTT_TOPIC *srcMqttTopic); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ AQH_HTTP_URLHANDLER *AQH_MqttTopicsHttpUrlHandler_new(AQH_SERVICE *sv) { AQH_HTTP_URLHANDLER *uh; uh=AQH_ObjectsHttpUrlHandler_new(sv, AQHOME_HTTP_PERMS_LIST_TOPICS, AQHOME_HTTP_PERMS_ADD_TOPIC, AQHOME_HTTP_PERMS_DEL_TOPIC, AQHOME_HTTP_PERMS_EDIT_TOPIC, "/mqtttopics/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_MQTT_TOPIC *newMqttTopic; const char *topic; int rv; sv=AQH_HttpUrlHandler_GetHttpService(uh); sto=AqHomeHttpService_GetStorage(sv); newMqttTopic=AQH_MqttTopic_fromDb(db); topic=AQH_MqttTopic_GetTopic(newMqttTopic); if (!(topic && *topic)) { DBG_INFO(NULL, "Missing mqttTopic topic"); AQH_MqttTopic_free(newMqttTopic); return GWEN_ERROR_INVALID; } rv=AqHomeHttpService_LockStorage(sv); if (rv<0) { DBG_ERROR(NULL, "Error locking storage"); AQH_MqttTopic_free(newMqttTopic); return GWEN_ERROR_IO; } if (id>0) { AQH_MQTT_TOPIC *mqttTopic; DBG_INFO(NULL, "Edit existing mqttTopic"); mqttTopic=AQH_Storage_GetMqttTopicById(sto, id); if (mqttTopic==NULL) { AqHomeHttpService_UnlockStorage(sv); DBG_ERROR(NULL, "MqttTopic %d not found", id); AQH_MqttTopic_free(newMqttTopic); return GWEN_ERROR_NOT_FOUND; } AQH_MqttTopic_SetId(mqttTopic, id); _setFromObject(mqttTopic, newMqttTopic); AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); } else { AQH_MQTT_TOPIC *mqttTopic; DBG_INFO(NULL, "Adding new mqttTopic"); mqttTopic=AQH_Storage_GetMqttTopicByTopic(sto, topic); if (mqttTopic) { AqHomeHttpService_UnlockStorage(sv); DBG_ERROR(NULL, "MqttTopic %s exists", topic); AQH_MqttTopic_free(newMqttTopic); return GWEN_ERROR_FOUND; } mqttTopic=AQH_MqttTopic_new(); AQH_MqttTopic_SetId(mqttTopic, 0); _setFromObject(mqttTopic, newMqttTopic); AQH_Storage_AddMqttTopic(sto, mqttTopic); AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); } AQH_MqttTopic_free(newMqttTopic); rv=AqHomeHttpService_UnlockStorage(sv); if (rv<0) { DBG_ERROR(NULL, "Error unlocking storage"); return GWEN_ERROR_IO; } return 0; } void _setFromObject(AQH_MQTT_TOPIC *mqttTopic, const AQH_MQTT_TOPIC *srcMqttTopic) { AQH_MqttTopic_SetDeviceId(mqttTopic, AQH_MqttTopic_GetDeviceId(srcMqttTopic)); AQH_MqttTopic_SetTopic(mqttTopic, AQH_MqttTopic_GetTopic(srcMqttTopic)); AQH_MqttTopic_SetDataType(mqttTopic, AQH_MqttTopic_GetDataType(srcMqttTopic)); } GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id) { AQH_SERVICE *sv; AQH_STORAGE *sto; const AQH_MQTT_TOPIC *mqttTopic; sv=AQH_HttpUrlHandler_GetHttpService(uh); sto=AqHomeHttpService_GetStorage(sv); mqttTopic=AQH_Storage_GetMqttTopicById(sto, id); if (mqttTopic) { GWEN_DB_NODE *db; db=GWEN_DB_Group_new("mqttTopic"); AQH_MqttTopic_toDb(mqttTopic, 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 MQTT Topic")); _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 MQTT Topic"), (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_DEVICE_LIST *deviceList; unsigned long int selectedDeviceId=0; int dataType; char numbuf[16]; sv=AQH_HttpUrlHandler_GetHttpService(uh); sto=AqHomeHttpService_GetStorage(sv); deviceList=AQH_Storage_GetDeviceList(sto); selectedDeviceId=(unsigned long int)(dbValues?GWEN_DB_GetIntValue(dbValues, "deviceId", 0, 0):0); snprintf(numbuf, sizeof(numbuf)-1, "%lu", selectedDeviceId); numbuf[sizeof(numbuf)-1]=0; dataType=dbValues?GWEN_DB_GetIntValue(dbValues, "dataType", 0, AQH_MqttTopicType_Num):0; /* topic */ GWEN_Buffer_AppendArgs(pageBuf, " " " " " " " " " ", I18N("MQTT Topic"), dbValues?GWEN_DB_GetCharValue(dbValues, "topic", 0, ""):""); GWEN_Buffer_AppendArgs(pageBuf, "" ""); /* data type */ GWEN_Buffer_AppendArgs(pageBuf, "" ""); GWEN_Buffer_AppendString(pageBuf, "
"); } void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf) { AQH_SERVICE *sv; AQH_STORAGE *sto; const AQH_MQTT_TOPIC_LIST *rl; sv=AQH_HttpUrlHandler_GetHttpService(uh); sto=AqHomeHttpService_GetStorage(sv); GWEN_Buffer_AppendArgs(pageBuf, "

%s

" "" "" " " "", I18N("Mqtt Topics"), I18N("Topic"), I18N("Device"), I18N("Datatype")); GWEN_Buffer_AppendString(pageBuf, ""); rl=AQH_Storage_GetMqttTopicList(sto); if (rl) { const AQH_MQTT_TOPIC *mqttTopic; mqttTopic=AQH_MqttTopic_List_First(rl); while(mqttTopic) { long unsigned int id; int deviceId; const char *topic; int dataType; const char *deviceName=NULL; const AQH_DEVICE *device=NULL; id=(long unsigned int) AQH_MqttTopic_GetId(mqttTopic); deviceId=(long unsigned int) AQH_MqttTopic_GetDeviceId(mqttTopic); if (deviceId>0) device=AQH_Storage_GetDeviceById(sto, deviceId); if (device) deviceName=AQH_Device_GetName(device); topic=AQH_MqttTopic_GetTopic(mqttTopic); dataType=AQH_MqttTopic_GetDataType(mqttTopic); GWEN_Buffer_AppendArgs(pageBuf, "" "" "", topic?topic:"", deviceName?deviceName:"", AQH_MqttTopicType_toString(dataType), id); mqttTopic=AQH_MqttTopic_List_Next(mqttTopic); } } GWEN_Buffer_AppendString(pageBuf, ""); GWEN_Buffer_AppendArgs(pageBuf, "
%s%s%s
%s%s%s" "
%s
", I18N("Add MqttTopic")); }