added url handler for mqtt topics.

This commit is contained in:
Martin Preuss
2023-08-11 01:24:31 +02:00
parent 96c2b9a649
commit c5171714b2
6 changed files with 389 additions and 3 deletions

View File

@@ -0,0 +1,340 @@
/****************************************************************************
* 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 "./u_mqtttopics.h"
#include "./u_objects.h"
#include "./aqhomehttp.h"
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/i18n.h>
/* ------------------------------------------------------------------------------------------------
* 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,
"<h2>%s</h2><br>\n"
"<form action=\"/mqtttopics/add\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">",
I18N("Add MQTT Topic"));
_writeEditingTable(uh, dbValues, pageBuf);
GWEN_Buffer_AppendArgs(pageBuf, "<input type=\"submit\" value=\"%s\"></form>", 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,
"<h2>%s</h2><br>\n"
"<form action=\"/mqtttopics/edit/%lu\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">",
I18N("Edit MQTT Topic"),
(long unsigned int)(dbValues?GWEN_DB_GetIntValue(dbValues, "id", 0, 0):0));
_writeEditingTable(uh, dbValues, pageBuf);
GWEN_Buffer_AppendArgs(pageBuf, "<input type=\"submit\" value=\"%s\"></form>", 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,
" <table>"
" <tr>"
" <td><label for=\"topic\">%s: </label></td>"
" <td><input type=\"text\" name=\"topic\" value=\"%s\" required></td>"
" </tr>",
I18N("MQTT Topic"),
dbValues?GWEN_DB_GetCharValue(dbValues, "topic", 0, ""):"");
GWEN_Buffer_AppendArgs(pageBuf,
"<tr><td><label for=\"deviceId\">%s: </label></td>"
"<td><select id=\"deviceId\" name=\"deviceId\">",
I18N("Device"));
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"0\">%s</option>", I18N("-- select device --"));
/* device */
if (deviceList) {
const AQH_DEVICE *device;
device=AQH_Device_List_First(deviceList);
while(device) {
const char *deviceName;
deviceName=AQH_Device_GetName(device);
if (deviceName && *deviceName) {
snprintf(numbuf, sizeof(numbuf)-1, "%lu", (unsigned long int) AQH_Device_GetId(device));
numbuf[sizeof(numbuf)-1]=0;
if (selectedDeviceId && AQH_Device_GetId(device)==selectedDeviceId)
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%s\" selected>%s</option>", numbuf, deviceName);
else
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%s\">%s</option>", numbuf, deviceName);
}
device=AQH_Device_List_Next(device);
}
}
GWEN_Buffer_AppendString(pageBuf, "</select></td></tr>");
/* data type */
GWEN_Buffer_AppendArgs(pageBuf,
"<tr><td><label for=\"dataType\">%s: </label></td>"
"<td><select id=\"dataType\" name=\"dataType\">",
I18N("Data Type"));
if (dataType==AQH_MqttTopicType_Num)
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%d\" selected>%s</option>", dataType, I18N("numeric"));
else
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%d\" >%s</option>", dataType, I18N("numeric"));
if (dataType==AQH_MqttTopicType_Json)
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%d\" selected>%s</option>", dataType, I18N("JSON"));
else
GWEN_Buffer_AppendArgs(pageBuf, "<option value=\"%d\" >%s</option>", dataType, I18N("JSON"));
GWEN_Buffer_AppendString(pageBuf, "</select></td></tr>");
GWEN_Buffer_AppendString(pageBuf, "</tbody></table>");
}
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,
"<h2>%s</h2>"
"<table class=\"dataTable\">"
"<thead>"
" <tr><th>%s</th><th>%s</th><th>%s</th><th></th></tr>"
"</thead>",
I18N("Mqtt Topics"),
I18N("Topic"),
I18N("Device"),
I18N("Datatype"));
GWEN_Buffer_AppendString(pageBuf, "<tbody>");
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,
"<tr><td>%s</td><td>%s</td><td>%s</td>"
"<td><a href=\"/mqtttopics/edit/%lu\">"
"<IMG src=\"/pics/edit.png\" width=32 height=32 align=left border=0></a></td>"
"</tr>",
topic?topic:"",
deviceName?deviceName:"",
AQH_MqttTopicType_toString(dataType),
id);
mqttTopic=AQH_MqttTopic_List_Next(mqttTopic);
}
}
GWEN_Buffer_AppendString(pageBuf, "</tbody>");
GWEN_Buffer_AppendArgs(pageBuf, "</table><a href=\"/mqtttopics/add\">%s</a><br>", I18N("Add MqttTopic"));
}