mirror of
https://github.com/rvdbreemen/OTGW-firmware
synced 2024-11-16 04:33:49 +01:00
293 lines
9.6 KiB
C++
293 lines
9.6 KiB
C++
/*
|
|
***************************************************************************
|
|
** Program : restAPI
|
|
** Version : v0.3.1
|
|
**
|
|
** Copyright (c) 2020 Robert van den Breemen
|
|
** based on Framework ESP8266 from Willem Aandewiel
|
|
**
|
|
** TERMS OF USE: MIT License. See bottom of file.
|
|
***************************************************************************
|
|
*/
|
|
|
|
|
|
//=======================================================================
|
|
void processAPI()
|
|
{
|
|
char fName[40] = "";
|
|
char URI[50] = "";
|
|
String words[10];
|
|
|
|
strlcpy( URI, httpServer.uri().c_str(), sizeof(URI) );
|
|
|
|
if (httpServer.method() == HTTP_GET)
|
|
DebugTf("from[%s] URI[%s] method[GET] \r\n"
|
|
, httpServer.client().remoteIP().toString().c_str()
|
|
, URI);
|
|
else DebugTf("from[%s] URI[%s] method[PUT] \r\n"
|
|
, httpServer.client().remoteIP().toString().c_str()
|
|
, URI);
|
|
|
|
if (ESP.getFreeHeap() < 8500) // to prevent firmware from crashing!
|
|
{
|
|
DebugTf("==> Bailout due to low heap (%d bytes))\r\n", ESP.getFreeHeap() );
|
|
httpServer.send(500, "text/plain", "500: internal server error (low heap)\r\n");
|
|
return;
|
|
}
|
|
|
|
int8_t wc = splitString(URI, '/', words, 10);
|
|
|
|
if (Verbose)
|
|
{
|
|
DebugT(">>");
|
|
for (int w=0; w<wc; w++)
|
|
{
|
|
Debugf("word[%d] => [%s], ", w, words[w].c_str());
|
|
}
|
|
Debugln(" ");
|
|
}
|
|
|
|
if (words[1] != "api")
|
|
{
|
|
sendApiNotFound(URI);
|
|
return;
|
|
}
|
|
|
|
if (words[2] != "v0")
|
|
{
|
|
sendApiNotFound(URI);
|
|
return;
|
|
}
|
|
|
|
if (words[3] == "otgw")
|
|
{
|
|
//what the heck should I do?
|
|
// /api/v0/otgw/{msgid} msgid = OpenTherm Message Id
|
|
// Response: label, value, unit
|
|
// {
|
|
// "label": "Tr",
|
|
// "value": "0.00",
|
|
// "unit": "°C"
|
|
// }
|
|
sendOTGWvalue(words[4].toInt());
|
|
}
|
|
else if (words[3] == "devinfo")
|
|
{
|
|
sendDeviceInfo();
|
|
}
|
|
else if (words[3] == "devtime")
|
|
{
|
|
sendDeviceTime();
|
|
}
|
|
else if (words[3] == "settings")
|
|
{
|
|
if (httpServer.method() == HTTP_PUT || httpServer.method() == HTTP_POST)
|
|
{
|
|
postSettings();
|
|
}
|
|
else
|
|
{
|
|
sendDeviceSettings();
|
|
}
|
|
}
|
|
else sendApiNotFound(URI);
|
|
|
|
} // processAPI()
|
|
|
|
|
|
//====[ implementing REST API ]====
|
|
void sendOTGWvalue(int msgid){
|
|
StaticJsonDocument<256> doc;
|
|
JsonObject root = doc.to<JsonObject>();
|
|
if (msgid<=127) {
|
|
//Debug print the values first
|
|
DebugTf("%s = %s %s\r\n", OTmap[msgid].label, getOTGWValue(msgid).c_str(), OTmap[msgid].unit);
|
|
//build the json
|
|
root["label"] = OTmap[msgid].label;
|
|
root["value"] = getOTGWValue(msgid);
|
|
root["unit"] = OTmap[msgid].unit;
|
|
} else {
|
|
root["error"] = "message id > 127: reserved for future use";
|
|
}
|
|
String sBuff;
|
|
serializeJsonPretty(root, sBuff);
|
|
//DebugTf("Json = %s\r\n", sBuff.c_str());
|
|
//reply with json
|
|
httpServer.sendHeader("Access-Control-Allow-Origin", "*");
|
|
httpServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
|
httpServer.send(200, "application/json", sBuff);
|
|
}
|
|
|
|
//=======================================================================
|
|
void sendDeviceInfo()
|
|
{
|
|
sendStartJsonObj("devinfo");
|
|
|
|
sendNestedJsonObj("author", "Robert van den Breemen");
|
|
sendNestedJsonObj("fwversion", _FW_VERSION);
|
|
|
|
snprintf(cMsg, sizeof(cMsg), "%s %s", __DATE__, __TIME__);
|
|
sendNestedJsonObj("compiled", cMsg);
|
|
sendNestedJsonObj("hostname", settingHostname);
|
|
sendNestedJsonObj("ipaddress", WiFi.localIP().toString().c_str());
|
|
sendNestedJsonObj("macaddress", WiFi.macAddress().c_str());
|
|
sendNestedJsonObj("freeheap", ESP.getFreeHeap());
|
|
sendNestedJsonObj("maxfreeblock", ESP.getMaxFreeBlockSize());
|
|
sendNestedJsonObj("chipid", String( ESP.getChipId(), HEX ).c_str());
|
|
sendNestedJsonObj("coreversion", String( ESP.getCoreVersion() ).c_str() );
|
|
sendNestedJsonObj("sdkversion", String( ESP.getSdkVersion() ).c_str());
|
|
sendNestedJsonObj("cpufreq", ESP.getCpuFreqMHz());
|
|
sendNestedJsonObj("sketchsize", formatFloat( (ESP.getSketchSize() / 1024.0), 3));
|
|
sendNestedJsonObj("freesketchspace", formatFloat( (ESP.getFreeSketchSpace() / 1024.0), 3));
|
|
|
|
snprintf(cMsg, sizeof(cMsg), "%08X", ESP.getFlashChipId());
|
|
sendNestedJsonObj("flashchipid", cMsg); // flashChipId
|
|
sendNestedJsonObj("flashchipsize", formatFloat((ESP.getFlashChipSize() / 1024.0 / 1024.0), 3));
|
|
sendNestedJsonObj("flashchiprealsize", formatFloat((ESP.getFlashChipRealSize() / 1024.0 / 1024.0), 3));
|
|
|
|
SPIFFS.info(SPIFFSinfo);
|
|
sendNestedJsonObj("spiffssize", formatFloat( (SPIFFSinfo.totalBytes / (1024.0 * 1024.0)), 0));
|
|
|
|
sendNestedJsonObj("flashchipspeed", formatFloat((ESP.getFlashChipSpeed() / 1000.0 / 1000.0), 0));
|
|
|
|
FlashMode_t ideMode = ESP.getFlashChipMode();
|
|
sendNestedJsonObj("flashchipmode", flashMode[ideMode]);
|
|
sendNestedJsonObj("boardtype",
|
|
#ifdef ARDUINO_ESP8266_NODEMCU
|
|
"ESP8266_NODEMCU"
|
|
#endif
|
|
#ifdef ARDUINO_ESP8266_GENERIC
|
|
"ESP8266_GENERIC"
|
|
#endif
|
|
#ifdef ESP8266_ESP01
|
|
"ESP8266_ESP01"
|
|
#endif
|
|
#ifdef ESP8266_ESP12
|
|
"ESP8266_ESP12"
|
|
#endif
|
|
);
|
|
sendNestedJsonObj("ssid", WiFi.SSID().c_str());
|
|
sendNestedJsonObj("wifirssi", WiFi.RSSI());
|
|
//sendNestedJsonObj("uptime", upTime());
|
|
|
|
sendNestedJsonObj("lastreset", lastReset);
|
|
|
|
httpServer.sendContent("\r\n]}\r\n");
|
|
|
|
} // sendDeviceInfo()
|
|
|
|
|
|
//=======================================================================
|
|
void sendDeviceTime()
|
|
{
|
|
char actTime[50];
|
|
|
|
sendStartJsonObj("devtime");
|
|
snprintf(actTime, 49, "%04d-%02d-%02d %02d:%02d:%02d", year(), month(), day()
|
|
, hour(), minute(), second());
|
|
sendNestedJsonObj("dateTime", actTime);
|
|
sendNestedJsonObj("epoch", (int)now());
|
|
|
|
sendEndJsonObj();
|
|
|
|
} // sendDeviceTime()
|
|
|
|
|
|
//=======================================================================
|
|
void sendDeviceSettings()
|
|
{
|
|
DebugTln("sending device settings ...\r");
|
|
|
|
sendStartJsonObj("settings");
|
|
|
|
sendJsonSettingObj("hostname", settingHostname, "s", sizeof(settingHostname) -1);
|
|
//sendJsonSettingObj("float", settingFloat, "f", 0, 10, 5);
|
|
//sendJsonSettingObj("intager", settingInteger , "i", 2, 60);
|
|
|
|
sendEndJsonObj();
|
|
|
|
} // sendDeviceSettings()
|
|
|
|
|
|
//=======================================================================
|
|
void postSettings()
|
|
{
|
|
//------------------------------------------------------------
|
|
// json string: {"name":"settingInterval","value":9}
|
|
// json string: {"name":"settingHostname","value":"abc"}
|
|
//------------------------------------------------------------
|
|
// so, why not use ArduinoJSON library?
|
|
// I say: try it yourself ;-) It won't be easy
|
|
String wOut[5];
|
|
String wPair[5];
|
|
String jsonIn = httpServer.arg(0).c_str();
|
|
char field[25] = "";
|
|
char newValue[101]="";
|
|
jsonIn.replace("{", "");
|
|
jsonIn.replace("}", "");
|
|
jsonIn.replace("\"", "");
|
|
int8_t wp = splitString(jsonIn.c_str(), ',', wPair, 5) ;
|
|
for (int i=0; i<wp; i++)
|
|
{
|
|
//DebugTf("[%d] -> pair[%s]\r\n", i, wPair[i].c_str());
|
|
int8_t wc = splitString(wPair[i].c_str(), ':', wOut, 5) ;
|
|
//DebugTf("==> [%s] -> field[%s]->val[%s]\r\n", wPair[i].c_str(), wOut[0].c_str(), wOut[1].c_str());
|
|
if (wOut[0].equalsIgnoreCase("name")) strCopy(field, sizeof(field), wOut[1].c_str());
|
|
if (wOut[0].equalsIgnoreCase("value")) strCopy(newValue, sizeof(newValue), wOut[1].c_str());
|
|
}
|
|
DebugTf("--> field[%s] => newValue[%s]\r\n", field, newValue);
|
|
updateSetting(field, newValue);
|
|
httpServer.send(200, "application/json", httpServer.arg(0));
|
|
|
|
} // postSettings()
|
|
|
|
|
|
//====================================================
|
|
void sendApiNotFound(const char *URI)
|
|
{
|
|
httpServer.sendHeader("Access-Control-Allow-Origin", "*");
|
|
httpServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
|
httpServer.send ( 404, "text/html", "<!DOCTYPE HTML><html><head>");
|
|
|
|
strlcpy(cMsg, "<style>body { background-color: lightgray; font-size: 15pt;}", sizeof(cMsg));
|
|
strlcat(cMsg, "</style></head><body>", sizeof(cMsg));
|
|
httpServer.sendContent(cMsg);
|
|
|
|
strlcpy(cMsg, "<h1>OTGW firmware</h1><b1>", sizeof(cMsg));
|
|
httpServer.sendContent(cMsg);
|
|
|
|
strlcpy(cMsg, "<br>[<b>", sizeof(cMsg));
|
|
strlcat(cMsg, URI, sizeof(cMsg));
|
|
strlcat(cMsg, "</b>] is not a valid ", sizeof(cMsg));
|
|
httpServer.sendContent(cMsg);
|
|
|
|
strlcpy(cMsg, "</body></html>\r\n", sizeof(cMsg));
|
|
httpServer.sendContent(cMsg);
|
|
|
|
} // sendApiNotFound()
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
* persons to whom the Software is furnished to do so, subject to the
|
|
* following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
|
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
****************************************************************************
|
|
*/
|