Browse Source

added command queue

+ command queue
+ feedback from inverter for actual power limit via InfoCmd -> SystemConfigPara (0x05)
+ REST API will enqueue a new info command
+ change in power limit will enqueue infocm to get actual power limit
+ actual power limit is available under mqtt topic <TOPIC>/<NAME>/ch0/PowerLimit ALWAYS in percent
+ Firmware information will be requested automatically up on start of dtu
pull/180/head
Andreas Schiffler 2 years ago
parent
commit
51fbe7868c
  1. 143
      tools/esp8266/app.cpp
  2. 24
      tools/esp8266/defines.h
  3. 10
      tools/esp8266/hmDefines.h
  4. 129
      tools/esp8266/hmInverter.h
  5. 3
      tools/esp8266/hmSystem.h
  6. 2
      tools/esp8266/html/h/index_html.h
  7. 6
      tools/esp8266/html/index.html
  8. 14
      tools/esp8266/web.cpp

143
tools/esp8266/app.cpp

@ -111,37 +111,6 @@ void app::loop(void) {
}
}
}
switch (mSys->InfoCmd){
case InverterDevInform_Simple:
{
DPRINT(DBG_INFO, "Response from inform simple\n");
break;
}
case InverterDevInform_All:
{
DPRINT(DBG_INFO, "Response from inform all\n");
break;
}
case GetLossRate:
{
DPRINT(DBG_INFO, "Response from get loss rate\n");
break;
}
case AlarmData:
{
DPRINT(DBG_INFO, "Response from AlarmData\n");
break;
}
case AlarmUpdate:
{
DPRINT(DBG_INFO, "Response from AlarmUpdate\n");
break;
}
case RealTimeRunData_Debug:
{
break;
}
}
}
if(NULL != iv && p->packet[0] == (TX_REQ_DEVCONTROL + 0x80)) { // response from dev control command
DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received"));
@ -180,7 +149,7 @@ void app::loop(void) {
if(rxRdy) {
processPayload(true,mSys->InfoCmd);
processPayload(true);
}
}
@ -266,7 +235,7 @@ void app::loop(void) {
if(NULL != iv) {
if(!mPayload[iv->id].complete)
processPayload(false,mSys->InfoCmd);
processPayload(false);
if(!mPayload[iv->id].complete) {
mRxFailed++;
@ -286,8 +255,9 @@ void app::loop(void) {
if(mConfig.serialDebug)
DPRINTLN(DBG_INFO, F("Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
mSys->Radio.sendControlPacket(iv->radioId.u64,iv->devControlCmd ,iv->powerLimit);
iv->enqueCommand<InfoCommand>(SystemConfigPara);
} else {
mSys->Radio.sendTimePacket(iv->radioId.u64, mSys->InfoCmd, mPayload[iv->id].ts,iv->alarmMesIndex);
mSys->Radio.sendTimePacket(iv->radioId.u64,iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex);
mRxTicker = 0;
}
}
@ -333,10 +303,7 @@ bool app::buildPayload(uint8_t id) {
//-----------------------------------------------------------------------------
void app::processPayload(bool retransmit) {
processPayload(retransmit, RealTimeRunData_Debug);
}
void app::processPayload(bool retransmit, uint8_t cmd = RealTimeRunData_Debug) { // cmd value decides which parser is used to decode payload
void app::processPayload(bool retransmit) {
#ifdef __MQTT_AFTER_RX__
boolean doMQTT = false;
@ -369,7 +336,7 @@ void app::processPayload(bool retransmit, uint8_t cmd = RealTimeRunData_Debug) {
if(0x00 != mLastPacketId)
mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true);
else
mSys->Radio.sendTimePacket(iv->radioId.u64, mSys->InfoCmd, mPayload[iv->id].ts,iv->alarmMesIndex);
mSys->Radio.sendTimePacket(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts,iv->alarmMesIndex);
}
mSys->Radio.switchRxCh(100);
}
@ -392,20 +359,18 @@ void app::processPayload(bool retransmit, uint8_t cmd = RealTimeRunData_Debug) {
mSys->Radio.dumpBuf(NULL, payload, offs);
}
mRxSuccess++;
mSys->InfoCmd = mSys->NextInfoCmd; // On success set next
mSys->NextInfoCmd = RealTimeRunData_Debug; // Set next to default. Can/will be overwritten by REST API
iv->getAssignment(cmd); // choose the parser
iv->getAssignment(); // choose the parser
for(uint8_t i = 0; i < iv->listLen; i++) {
iv->addValue(i, payload,cmd); // cmd value decides which parser is used to decode payload
iv->addValue(i, payload); // cmd value decides which parser is used to decode payload
yield();
}
iv->doCalculations(cmd); // cmd value decides which parser is used to decode payload
iv->doCalculations(); // cmd value decides which parser is used to decode payload
#ifdef __MQTT_AFTER_RX__
doMQTT = true;
#endif
iv->setQueuedCmdFinished();
}
}
yield();
@ -560,32 +525,48 @@ String app::getStatistics(void) {
//-----------------------------------------------------------------------------
String app::getLiveData(void) {
String app::getLiveData(void)
{
String modHtml;
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
for (uint8_t id = 0; id < mSys->getNumInverters(); id++)
{
Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL != iv) {
if (NULL != iv)
{
#ifdef LIVEDATA_VISUALIZED
uint8_t modNum, pos;
switch(iv->type) {
default:
case INV_TYPE_1CH: modNum = 1; break;
case INV_TYPE_2CH: modNum = 2; break;
case INV_TYPE_4CH: modNum = 4; break;
switch (iv->type)
{
default:
case INV_TYPE_1CH:
modNum = 1;
break;
case INV_TYPE_2CH:
modNum = 2;
break;
case INV_TYPE_4CH:
modNum = 4;
break;
}
modHtml += F("<div class=\"iv\">"
"<div class=\"ch-iv\"><span class=\"head\">") + String(iv->name) + F(" Limit ") + String(iv->powerLimit[0]);
if (iv->powerLimit[1] & 0x0001){
"<div class=\"ch-iv\"><span class=\"head\">") +
String(iv->name) + F(" Limit ") + String(iv->actPowerLimit);
if (true)
{ // live Power Limit from inverter is always in %
modHtml += F(" %</span>");
} else {
}
else
{
modHtml += F(" W</span>");
}
uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_PRA, FLD_ALARM_MES_ID};
for(uint8_t fld = 0; fld < 12; fld++) {
for (uint8_t fld = 0; fld < 12; fld++)
{
pos = (iv->getPosByChFld(CH0, list[fld]));
if(0xff != pos) {
if (0xff != pos)
{
modHtml += F("<div class=\"subgrp\">");
modHtml += F("<span class=\"value\">") + String(iv->getValue(pos));
modHtml += F("<span class=\"unit\">") + String(iv->getUnit(pos)) + F("</span></span>");
@ -595,23 +576,39 @@ String app::getLiveData(void) {
}
modHtml += "</div>";
for(uint8_t ch = 1; ch <= modNum; ch ++) {
for (uint8_t ch = 1; ch <= modNum; ch++)
{
modHtml += F("<div class=\"ch\"><span class=\"head\">");
if(iv->chName[ch-1][0] == 0)
if (iv->chName[ch - 1][0] == 0)
modHtml += F("CHANNEL ") + String(ch);
else
modHtml += String(iv->chName[ch-1]);
modHtml += String(iv->chName[ch - 1]);
modHtml += F("</span>");
for(uint8_t j = 0; j < 6; j++) {
switch(j) {
default: pos = (iv->getPosByChFld(ch, FLD_UDC)); break;
case 1: pos = (iv->getPosByChFld(ch, FLD_IDC)); break;
case 2: pos = (iv->getPosByChFld(ch, FLD_PDC)); break;
case 3: pos = (iv->getPosByChFld(ch, FLD_YD)); break;
case 4: pos = (iv->getPosByChFld(ch, FLD_YT)); break;
case 5: pos = (iv->getPosByChFld(ch, FLD_IRR)); break;
for (uint8_t j = 0; j < 6; j++)
{
switch (j)
{
default:
pos = (iv->getPosByChFld(ch, FLD_UDC));
break;
case 1:
pos = (iv->getPosByChFld(ch, FLD_IDC));
break;
case 2:
pos = (iv->getPosByChFld(ch, FLD_PDC));
break;
case 3:
pos = (iv->getPosByChFld(ch, FLD_YD));
break;
case 4:
pos = (iv->getPosByChFld(ch, FLD_YT));
break;
case 5:
pos = (iv->getPosByChFld(ch, FLD_IRR));
break;
}
if(0xff != pos) {
if (0xff != pos)
{
modHtml += F("<span class=\"value\">") + String(iv->getValue(pos));
modHtml += F("<span class=\"unit\">") + String(iv->getUnit(pos)) + F("</span></span>");
modHtml += F("<span class=\"info\">") + String(iv->getFieldName(pos)) + F("</span>");
@ -626,7 +623,8 @@ String app::getLiveData(void) {
// dump all data to web frontend
modHtml = F("<pre>");
char topic[30], val[10];
for(uint8_t i = 0; i < iv->listLen; i++) {
for (uint8_t i = 0; i < iv->listLen; i++)
{
snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i));
snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i));
modHtml += String(topic) + ": " + String(val) + "\n";
@ -638,7 +636,6 @@ String app::getLiveData(void) {
return modHtml;
}
//-----------------------------------------------------------------------------
String app::getJson(void) {
DPRINTLN(DBG_VERBOSE, F("app::showJson"));

24
tools/esp8266/defines.h

@ -25,22 +25,22 @@ typedef struct {
typedef enum {
InverterDevInform_Simple = 0, // 0x00
InverterDevInform_All = 1, // 0x01
//GridOnProFilePara = 2, // 0x02
//HardWareConfig = 3, // 0x03
//SimpleCalibrationPara = 4, // 0x04
//SystemConfigPara = 5, // 0x05
GridOnProFilePara = 2, // 0x02
HardWareConfig = 3, // 0x03
SimpleCalibrationPara = 4, // 0x04
SystemConfigPara = 5, // 0x05
RealTimeRunData_Debug = 11, // 0x0b
//RealTimeRunData_Reality = 12, // 0x0c
//RealTimeRunData_A_Phase = 13, // 0x0d
//RealTimeRunData_B_Phase = 14, // 0x0e
//RealTimeRunData_C_Phase = 15, // 0x0f
RealTimeRunData_Reality = 12, // 0x0c
RealTimeRunData_A_Phase = 13, // 0x0d
RealTimeRunData_B_Phase = 14, // 0x0e
RealTimeRunData_C_Phase = 15, // 0x0f
AlarmData = 17, // 0x11, Alarm data - all unsent alarms
AlarmUpdate = 18, // 0x12, Alarm data - all pending alarms
//RecordData = 19, // 0x13
//InternalData = 20, // 0x14
RecordData = 19, // 0x13
InternalData = 20, // 0x14
GetLossRate = 21, // 0x15
//GetSelfCheckState = 30, // 0x1e
//InitDataState = 0xff
GetSelfCheckState = 30, // 0x1e
InitDataState = 0xff
} InfoCmdType;
typedef enum {

10
tools/esp8266/hmDefines.h

@ -23,9 +23,9 @@ const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%","VAr",
// field types
enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT,
FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR,FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID};
FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT, FLD_EFF, FLD_IRR, FLD_PRA,FLD_ALARM_MES_ID,FLD_FW_VERSION,FLD_FW_BUILD_YEAR,FLD_FW_BUILD_MONTH_DAY,FLD_HW_ID,FLD_ACT_PWR_LIMIT};
const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal",
"U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr","ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId"};
"U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct", "Efficiency", "Irradiation","P_ACr","ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","HWPartId","PowerLimit"};
// mqtt discovery device classes
enum {DEVICE_CLS_NONE = 0, DEVICE_CLS_CURRENT, DEVICE_CLS_ENERGY, DEVICE_CLS_PWR, DEVICE_CLS_VOLTAGE, DEVICE_CLS_FREQ, DEVICE_CLS_TEMP};
@ -92,6 +92,12 @@ const byteAssign_t InfoAssignment[] = {
};
#define HMINFO_LIST_LEN (sizeof(InfoAssignment) / sizeof(byteAssign_t))
const byteAssign_t SystemConfigParaAssignment[] = {
{ FLD_ACT_PWR_LIMIT, UNIT_PCT, CH0, 2, 2, 10 }
};
#define HMSYSTEM_LIST_LEN (sizeof(SystemConfigParaAssignment) / sizeof(byteAssign_t))
//-------------------------------------

129
tools/esp8266/hmInverter.h

@ -12,6 +12,8 @@
#endif
#include "hmDefines.h"
#include <memory>
#include <queue>
/**
* For values which are of interest and not transmitted by the inverter can be
@ -51,8 +53,34 @@ template<class T=float>
struct calcFunc_t {
uint8_t funcId; // unique id
func_t<T>* func; // function pointer
} ;
};
class CommandAbstract {
public:
CommandAbstract(uint8_t txType = 0, uint8_t cmd = 0){
_TxType = txType;
_Cmd = cmd;
};
virtual ~CommandAbstract() {};
const uint8_t getCmd()
{
return _Cmd;
}
protected:
uint8_t _TxType;
uint8_t _Cmd;
};
class InfoCommand : public CommandAbstract {
public:
InfoCommand(uint8_t cmd){
_TxType = 0x15;
_Cmd = cmd;
}
};
// list of all available functions, mapped in hmDefines.h
template<class T=float>
@ -77,6 +105,7 @@ class Inverter {
uint16_t alarmMesIndex; // Last recorded Alarm Message Index
uint16_t fwVersion; // Firmware Version from Info Command Request
uint16_t powerLimit[2]; // limit power output
uint16_t actPowerLimit; //
uint8_t devControlCmd; // carries the requested cmd
bool devControlRequest; // true if change needed
serial_u serial; // serial number as on barcode
@ -92,6 +121,7 @@ class Inverter {
ts = 0;
powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited
powerLimit[1] = 0x0000; //
actPowerLimit = 0xffff; // init feedback from inverter to -1
devControlRequest = false;
devControlCmd = 0xff;
initialized = false;
@ -102,6 +132,30 @@ class Inverter {
// TODO: cleanup
}
template <typename T>
void enqueCommand(uint8_t cmd)
{
_commandQueue.push(std::make_shared<T>(cmd));
DPRINTLN(DBG_INFO, "enqueuedCmd: " + String(cmd));
}
void setQueuedCmdFinished(){
if (!_commandQueue.empty()){
_commandQueue.pop(); // Will destroy CommandAbstract Class Object (?)
}
}
uint8_t getQueuedCmd()
{
if (_commandQueue.empty()){
// Fill with default commands
enqueCommand<InfoCommand>(RealTimeRunData_Debug);
//enqueCommand<InfoCommand>(SystemConfigPara);
}
return _commandQueue.front().get()->getCmd();
}
void init(void) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:init"));
getAssignment();
@ -110,6 +164,8 @@ class Inverter {
memset(name, 0, MAX_NAME_LENGTH);
memset(chName, 0, MAX_NAME_LENGTH * 4);
memset(record, 0, sizeof(RECORDTYPE) * listLen);
enqueCommand<InfoCommand>(InverterDevInform_All);
enqueCommand<InfoCommand>(SystemConfigPara);
initialized = true;
}
@ -138,8 +194,9 @@ class Inverter {
return assign[pos].ch;
}
void addValue(uint8_t pos, uint8_t buf[],uint8_t cmd) {
void addValue(uint8_t pos, uint8_t buf[]) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue"));
uint8_t cmd = getQueuedCmd();
uint8_t ptr = assign[pos].start;
uint8_t end = ptr + assign[pos].num;
uint16_t div = assign[pos].div;
@ -149,8 +206,7 @@ class Inverter {
val <<= 8;
val |= buf[ptr];
} while(++ptr != end);
record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
}
if (cmd == RealTimeRunData_Debug) {
// get last alarm message index and save it in the inverter object
@ -165,6 +221,13 @@ class Inverter {
DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion));
}
}
if (cmd == SystemConfigPara) {
// get at least the firmware version and save it to the inverter object
if (getPosByChFld(0, FLD_ACT_PWR_LIMIT) == pos){
actPowerLimit = record[pos];
DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit));
}
}
}
RECORDTYPE getValue(uint8_t pos) {
@ -172,9 +235,10 @@ class Inverter {
return record[pos];
}
void doCalculations(uint8_t cmd=RealTimeRunData_Debug) {
void doCalculations() {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:doCalculations"));
getAssignment(cmd);
uint8_t cmd = getQueuedCmd();
getAssignment();
if (cmd == RealTimeRunData_Debug){
for(uint8_t i = 0; i < listLen; i++) {
if(CMD_CALC == assign[i].div) {
@ -204,37 +268,52 @@ class Inverter {
return ts;
}
void getAssignment(uint8_t cmd=RealTimeRunData_Debug) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getAssignment"));
if(cmd == RealTimeRunData_Debug){
if(INV_TYPE_1CH == type) {
listLen = (uint8_t)(HM1CH_LIST_LEN);
assign = (byteAssign_t*)hm1chAssignment;
void getAssignment() {
DPRINTLN(DBG_DEBUG, F("hmInverter.h:getAssignment"));
uint8_t cmd = getQueuedCmd();
switch (cmd)
{
case RealTimeRunData_Debug:
if (INV_TYPE_1CH == type)
{
listLen = (uint8_t)(HM1CH_LIST_LEN);
assign = (byteAssign_t *)hm1chAssignment;
channels = 1;
}
else if(INV_TYPE_2CH == type) {
listLen = (uint8_t)(HM2CH_LIST_LEN);
assign = (byteAssign_t*)hm2chAssignment;
else if (INV_TYPE_2CH == type)
{
listLen = (uint8_t)(HM2CH_LIST_LEN);
assign = (byteAssign_t *)hm2chAssignment;
channels = 2;
}
else if(INV_TYPE_4CH == type) {
listLen = (uint8_t)(HM4CH_LIST_LEN);
assign = (byteAssign_t*)hm4chAssignment;
else if (INV_TYPE_4CH == type)
{
listLen = (uint8_t)(HM4CH_LIST_LEN);
assign = (byteAssign_t *)hm4chAssignment;
channels = 4;
}
else {
listLen = 0;
else
{
listLen = 0;
channels = 0;
assign = NULL;
assign = NULL;
}
}
if(cmd == InverterDevInform_All){
listLen = (uint8_t)(HMINFO_LIST_LEN);
assign = (byteAssign_t*)InfoAssignment;
break;
case InverterDevInform_All:
listLen = (uint8_t)(HMINFO_LIST_LEN);
assign = (byteAssign_t *)InfoAssignment;
break;
case SystemConfigPara:
listLen = (uint8_t)(HMSYSTEM_LIST_LEN);
assign = (byteAssign_t *)SystemConfigParaAssignment;
break;
default:
DPRINTLN(DBG_INFO, "Parser not implemented");
}
}
private:
std::queue<std::shared_ptr<CommandAbstract>> _commandQueue;
void toRadioId(void) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId"));
radioId.u64 = 0ULL;

3
tools/esp8266/hmSystem.h

@ -19,13 +19,10 @@ class HmSystem {
RadioType Radio;
typedef BUFFER BufferType;
BufferType BufCtrl;
InfoCmdType NextInfoCmd; // For cmd-queue FIFO with one place
InfoCmdType InfoCmd; // For cmd-queue FIFO with one place
//DevControlCmdType DevControlCmd;
HmSystem() {
mNumInv = 0;
InfoCmd = RealTimeRunData_Debug; // default case
}
~HmSystem() {
// TODO: cleanup

2
tools/esp8266/html/h/index_html.h

@ -1,4 +1,4 @@
#ifndef __INDEX_HTML_H__
#define __INDEX_HTML_H__
const char index_html[] PROGMEM = "<!doctype html><html><head><title>Index - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><script type=\"text/javascript\">document.addEventListener('DOMContentLoaded', function(){document.getElementById(\"btn_req_fw\").addEventListener(\"click\", function(){getInverterInfo(`{\"inverter\":0,\"tx_request\": 21,\"cmd\": 1}`);});});getAjax('/uptime', 'uptime');getAjax('/cmdstat', 'cmds');window.setInterval(\"getAjax('/uptime', 'uptime')\", {JS_TS});window.setInterval(\"getAjax('/cmdstat', 'cmds')\", {JS_TS});function getAjax(url, resid) {var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"GET\", url, true);http.onreadystatechange = print;http.send(null);}function print() {if(http.readyState == 4) {document.getElementById(resid).innerHTML = http.responseText;}}}function getInverterInfo(data){var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"POST\", \"/api\");http.setRequestHeader(\"Accept\", \"application/json\");http.setRequestHeader(\"Content-Type\", \"application/json\");http.send(data);}}</script></head><body><h1>AHOY - {DEVICE}</h1><div id=\"content\" class=\"content\"><p><a href=\"/visualization\">Visualization</a><br/><br/><a href=\"/setup\">Setup</a><br/></p><p><span class=\"des\">Uptime: </span><span id=\"uptime\"></span></p><p><span class=\"des\">Statistics: </span><pre id=\"cmds\"></pre></p><p>Every {TS}seconds the values are updated</p><p><input type=\"button\" id=\"btn_req_fw\" value=\"Get FW-Info\"/></p><div id=\"note\">This project was started from <a href=\"https://www.mikrocontroller.net/topic/525778\" target=\"_blank\">this discussion. (Mikrocontroller.net)</a><br/>New updates can be found on Github: <a href=\"https://github.com/grindylow/ahoy\" target=\"_blank\">https://github.com/grindylow/ahoy</a><br/><br/>Please report issues using the feature provided by <a href=\"https://github.com/grindylow/ahoy/issues\">Github</a><br/><br/>Discuss with us on <a href=\"https://discord.gg/WzhxEY62mB\">Discord</a><br/><p class=\"lic\"><a href=\"https://creativecommons.org/licenses/by-nc-sa/3.0/de\">Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/</a><br/>Check the licenses which are published on <a href=\"https://github.com/grindylow/ahoy\">https://github.com/grindylow/ahoy</a>as well</p></div></div><div id=\"footer\"><p class=\"left\">&copy 2022</p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY :: {VERSION}</p><p class=\"right\"><a href=\"/reboot\">Reboot</a></p><p class=\"right\">Git SHA: {BUILD}</p></div></body></html>";
const char index_html[] PROGMEM = "<!doctype html><html><head><title>Index - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><script type=\"text/javascript\">getAjax('/uptime', 'uptime');getAjax('/cmdstat', 'cmds');window.setInterval(\"getAjax('/uptime', 'uptime')\", {JS_TS});window.setInterval(\"getAjax('/cmdstat', 'cmds')\", {JS_TS});function getAjax(url, resid) {var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"GET\", url, true);http.onreadystatechange = print;http.send(null);}function print() {if(http.readyState == 4) {document.getElementById(resid).innerHTML = http.responseText;}}}function getInverterInfo(data){var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"POST\", \"/api\");http.setRequestHeader(\"Accept\", \"application/json\");http.setRequestHeader(\"Content-Type\", \"application/json\");http.send(data);}}</script></head><body><h1>AHOY - {DEVICE}</h1><div id=\"content\" class=\"content\"><p><a href=\"/visualization\">Visualization</a><br/><br/><a href=\"/setup\">Setup</a><br/></p><p><span class=\"des\">Uptime: </span><span id=\"uptime\"></span></p><p><span class=\"des\">Statistics: </span><pre id=\"cmds\"></pre></p><p>Every {TS}seconds the values are updated</p><div id=\"note\">This project was started from <a href=\"https://www.mikrocontroller.net/topic/525778\" target=\"_blank\">this discussion. (Mikrocontroller.net)</a><br/>New updates can be found on Github: <a href=\"https://github.com/grindylow/ahoy\" target=\"_blank\">https://github.com/grindylow/ahoy</a><br/><br/>Please report issues using the feature provided by <a href=\"https://github.com/grindylow/ahoy/issues\">Github</a><br/><br/>Discuss with us on <a href=\"https://discord.gg/WzhxEY62mB\">Discord</a><br/><p class=\"lic\"><a href=\"https://creativecommons.org/licenses/by-nc-sa/3.0/de\">Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/</a><br/>Check the licenses which are published on <a href=\"https://github.com/grindylow/ahoy\">https://github.com/grindylow/ahoy</a>as well</p></div></div><div id=\"footer\"><p class=\"left\">&copy 2022</p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY :: {VERSION}</p><p class=\"right\"><a href=\"/reboot\">Reboot</a></p><p class=\"right\">Git SHA: {BUILD}</p></div></body></html>";
#endif /*__INDEX_HTML_H__*/

6
tools/esp8266/html/index.html

@ -5,11 +5,6 @@
<link rel="stylesheet" type="text/css" href="style.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function(){
document.getElementById("btn_req_fw").addEventListener("click", function(){
getInverterInfo(`{"inverter":0,"tx_request": 21,"cmd": 1}`);
});
});
getAjax('/uptime', 'uptime');
getAjax('/cmdstat', 'cmds');
window.setInterval("getAjax('/uptime', 'uptime')", {JS_TS});
@ -53,7 +48,6 @@
<p><span class="des">Uptime: </span><span id="uptime"></span></p>
<p><span class="des">Statistics: </span><pre id="cmds"></pre></p>
<p>Every {TS}seconds the values are updated</p>
<p><input type="button" id="btn_req_fw" value="Get FW-Info"/></p>
<div id="note">
This project was started from <a href="https://www.mikrocontroller.net/topic/525778" target="_blank">this discussion. (Mikrocontroller.net)</a><br/>

14
tools/esp8266/web.cpp

@ -443,19 +443,19 @@ void web::showWebApi(void)
deserializeJson(response, mWeb->arg("plain"));
// ToDo: error handling for payload
uint8_t iv_id = response["inverter"];
uint8_t cmd = response["cmd"];
Inverter<> *iv = mMain->mSys->getInverterByPos(iv_id);
if (NULL != iv)
{
if (response["tx_request"] == (uint8_t)TX_REQ_INFO)
{
//mMain->resetPayload(iv); // start request from new
mMain->mSys->NextInfoCmd = response["cmd"];
// process payload from web request corresponding to the cmd
if (mMain->mSys->NextInfoCmd == AlarmData)
// if the AlarmData is requested set the Alarm Index to the requested one
if (cmd == AlarmData){
iv->alarmMesIndex = response["payload"];
DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(mMain->mSys->InfoCmd) + F(" and payload ") + String((uint16_t) response["payload"]));
//DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(mMain->mSys->InfoCmd) + F(" and payload "));
}
DPRINTLN(DBG_INFO, F("Will make tx-request 0x15 with subcmd ") + String(cmd) + F(" and payload ") + String(response["payload"]));
// process payload from web request corresponding to the cmd
iv->enqueCommand<InfoCommand>(cmd);
}

Loading…
Cancel
Save