aqhome-cgi: added setdata.html

This commit is contained in:
Martin Preuss
2025-10-07 00:26:57 +02:00
parent 15728e27ca
commit 2a1af6f947

View File

@@ -32,6 +32,7 @@
#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD
#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD
#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE
@@ -48,10 +49,17 @@ static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session
static void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
static void _handleRqValuesGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
static void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
static void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
static void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
static void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
static void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf);
static void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf);
static void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf);
static uint32_t _colorFromHexString(const char *s);
/* ------------------------------------------------------------------------------------------------
@@ -60,8 +68,9 @@ static void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, A
*/
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
{"index.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD, _handleRqIndexGet},
{"values.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesGet},
{"index.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD, _handleRqIndexGet},
{"values.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesGet},
{"setdata.html", AQCGI_REQUEST_METHOD_POST, P_VALUEWRITE, _handleRqSetDataPost},
{NULL, 0, 0, NULL}
};
@@ -186,6 +195,13 @@ void _handleRqValuesGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session,
void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
{
AQH_ModDataClient_HandleRequest(m, rq, session, _runSetData, dbuf);
}
void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
{
AQH_DEVICE_LIST *deviceList;
@@ -210,11 +226,13 @@ void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATAC
"<th>Room</th>"
"<th>Location</th>"
"<th>Description</th>"
#if 0
"<th>Type</th>"
"<th>Driver</th>"
"<th>Name</th>"
"<th>GUI Name</th>"
"<th>Manufacturer</th>"
#endif
"</tr>\n"
"</thead>\n"
"<tbody>\n");
@@ -242,6 +260,7 @@ void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATAC
/* description */
s=AQH_Device_GetDescription(device);
GBAA(dbuf, "<td>%s</td>", s?s:"");
#if 0
/* device type */
s=AQH_Device_GetDeviceType(device);
GBAA(dbuf, "<td>%s</td>", s?s:"");
@@ -257,6 +276,7 @@ void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATAC
/* manufacturer */
s=AQH_Device_GetManufacturer(device);
GBAA(dbuf, "<td>%s</td>", s?s:"");
#endif
GBAA(dbuf, "</tr>");
device=AQH_Device_List_Next(device);
@@ -283,64 +303,282 @@ void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATA
AQH_VALUE_LIST *valueList;
valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0);
if (valueList) {
AQH_VALUE *value;
if (valueList && AQH_Value_List_GetCount(valueList)) {
GBAA(dbuf, "<h1>Values for Device %s</h1>\n", sDeviceName);
GBAS(dbuf,
"<table class=\"datatable\">\n"
"<thead>"
"<tr>"
"<th>Name</th>"
"<th>Type</th>"
"<th>Modality</th>"
"<th>Driver</th>"
"<th>Device</th>"
"<th>Name for System</th>"
"</tr>"
"</thead>\n"
"<tbody>\n");
GBAA(dbuf,"<h1>Values for Device %s</h1>\n", sDeviceName);
value=AQH_Value_List_First(valueList);
while(value) {
const char *s;
GBAS(dbuf,"<form action=\"setdata.html\" method=\"post\">\n");
GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
_writeValueListToTable(valueList, dbuf);
GBAS(dbuf, "<tr>");
s=AQH_Value_GetName(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_ValueType_toString(AQH_Value_GetValueType(value));
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_ValueModality_toString(AQH_Value_GetModality(value));
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_Value_GetDriver(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_Value_GetDeviceNameForSystem(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_Value_GetNameForSystem(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
GBAA(dbuf, "</tr>\n");
value=AQH_Value_List_Next(value);
}
GBAS(dbuf,
"</tbody>\n"
"</table>\n");
AQH_Value_List_free(valueList);
GBAS(dbuf,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
GBAS(dbuf, "</form>\n\n");
}
else {
GBAS(dbuf,"<p>No values.</p>\n");
}
AQH_Value_List_free(valueList);
}
}
void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf)
{
AQH_SERVICE *sv;
GWEN_DB_NODE *dbPost;
const char *sDeviceName;
AQH_VALUE_LIST *valueList;
/* sample data */
sv=AQH_ModService_GetService(m);
dbPost=AQCGI_Request_GetDbPostBody(rq);
sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL;
valueList=sDeviceName?AQH_DataClient_GetValues(dc, sDeviceName, 0):NULL;
if (valueList && AQH_Value_List_GetCount(valueList)) {
const AQH_VALUE *value;
value=AQH_Value_List_First(valueList);
while(value) {
if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) {
const char *sValueSystemName;
const char *sValueName;
const char *sValue;
int rv;
sValueSystemName=AQH_Value_GetNameForSystem(value);
sValueName=AQH_Value_GetName(value);
sValue=GWEN_DB_GetCharValue(dbPost, sValueName, 0, NULL);
if (sValueName && *sValueName) {
DBG_ERROR(NULL, "Setting value %s to %s", sValueName?sValueName:"no name", sValue?sValue:"no value");
switch(AQH_Value_GetModality(value)) {
case AQH_ValueModality_RGBW:
if (sValue) {
uint32_t color;
char colbuf[16];
color=_colorFromHexString(sValue);
snprintf(colbuf, sizeof(colbuf), "0x%08x", color);
DBG_ERROR(NULL, "Send value [%s] to %s", colbuf, sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, colbuf);
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
GBAA(dbuf, "<p>Error setting value for %s</p>", sValueSystemName);
}
}
break;
case AQH_ValueModality_OnOff:
if (sValue) {
if (strcasecmp(sValue, "unchanged")==0) {
DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName);
}
else if (strcasecmp(sValue, "on")==0) {
DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, "1");
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
}
}
else if (strcasecmp(sValue, "off")==0) {
DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, "0");
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
}
}
else {
}
}
break;
case AQH_ValueModality_OnOffAuto:
if (sValue) {
if (strcasecmp(sValue, "unchanged")==0) {
DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName);
}
else if (strcasecmp(sValue, "on")==0) {
DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, "1");
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
}
}
else if (strcasecmp(sValue, "off")==0) {
DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, "0");
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
}
}
else if (strcasecmp(sValue, "auto")==0) {
DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName);
rv=AQH_DataClient_SetData(dc, value, "2");
if (rv<0) {
DBG_ERROR(NULL, "Error sending data: %d", rv);
}
}
else {
DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName);
}
}
break;
default:
break;
} /* switch */
} /* if (sValueName) */
}
value=AQH_Value_List_Next(value);
} /* while */
}
AQH_Value_List_free(valueList);
if (sDeviceName && *sDeviceName) {
GWEN_BUFFER *pbuf;
pbuf=GWEN_Buffer_new(0, 256, 0, 1);
GBAS(pbuf, "Location: /aqbt/devices/values.html?device=");
GWEN_Text_EscapeToBufferTolerant(sDeviceName, pbuf);
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf));
GWEN_Buffer_free(pbuf);
}
AQCGI_Request_SetResponseCode(rq, 303);
AQCGI_Request_SetResponseText(rq, "See other");
}
void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf)
{
const AQH_VALUE *value;
GBAS(dbuf,
"<table class=\"datatable\">\n"
"<thead>"
"<tr>"
"<th>Name</th>"
"<th>Type</th>"
"<th>Modality</th>"
#if 0
"<th>Driver</th>"
"<th>Device</th>"
"<th>Name for System</th>"
#endif
"<th>Action</th>"
"</tr>"
"</thead>\n"
"<tbody>\n");
value=AQH_Value_List_First(valueList);
while(value) {
_writeValueToTable(value, dbuf);
value=AQH_Value_List_Next(value);
}
GBAS(dbuf,
"</tbody>\n"
"</table>\n");
}
void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf)
{
const char *s;
GBAS(dbuf, "<tr>");
s=AQH_Value_GetName(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_ValueType_toString(AQH_Value_GetValueType(value));
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_ValueModality_toString(AQH_Value_GetModality(value));
GBAA(dbuf, "<td>%s</td>", s?s:"");
#if 0
s=AQH_Value_GetDriver(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_Value_GetDeviceNameForSystem(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
s=AQH_Value_GetNameForSystem(value);
GBAA(dbuf, "<td>%s</td>", s?s:"");
#endif
GBAS(dbuf, "<td>");
if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor)
_addValueActionToForm(value, dbuf);
GBAS(dbuf, "</td>");
GBAA(dbuf, "</tr>\n");
}
void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf)
{
const char *sValueName;
sValueName=AQH_Value_GetName(value);
switch(AQH_Value_GetModality(value)) {
case AQH_ValueModality_RGBW:
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"refresh\"/>", sValueName);
break;
case AQH_ValueModality_OnOff:
GBAA(dbuf,
"<select name=\"%s\">"
"<option value=\"unchanged\">unchanged</option>"
"<option value=\"off\">off</option>"
"<option value=\"on\">on</option>"
"</select>",
sValueName);
break;
case AQH_ValueModality_OnOffAuto:
GBAA(dbuf,
"<select name=\"%s\">"
"<option value=\"unchanged\">unchanged</option>"
"<option value=\"off\">off</option>"
"<option value=\"on\">on</option>"
"<option value=\"auto\">auto</option>"
"</select>",
sValueName);
break;
default:
break;
}
}
uint32_t _colorFromHexString(const char *s)
{
uint32_t colorIn=0;
uint32_t colorOut;
while(*s && *s<33)
s++;
if (*s=='#')
s++;
while(*s) {
uint c;
c=(*s)-'0';
if (c>9)
c-=7;
colorIn<<=4;
colorIn|=c & 0xf;
s++;
}
/* hex 00RRGGBB -> GGRRWWBB */
colorOut=(colorIn & 0x00ff0000) | ((colorIn & 0x00ff00)<<16) | (colorIn & 0x0000ff);
return colorOut;
}