Browse Source

improved payload handling (request / retransmit) #464

included alarm ID parse to serial console (in development)
pull/635/head
lumapu 2 years ago
parent
commit
3d3e3dc8c6
  1. 7
      src/CHANGES.md
  2. 2
      src/app.cpp
  3. 1
      src/app.h
  4. 2
      src/defines.h
  5. 2
      src/hm/hmDefines.h
  6. 67
      src/hm/hmInverter.h
  7. 4
      src/hm/hmRadio.h
  8. 131
      src/hm/payload.h
  9. 8
      src/publisher/pubMqtt.h
  10. 9
      src/utils/helper.cpp
  11. 1
      src/utils/helper.h
  12. 15
      src/web/RestApi.h
  13. 6
      src/web/web.h

7
src/CHANGES.md

@ -2,6 +2,13 @@
(starting from release version `0.5.66`)
## 0.5.73
* improved payload handling (request / retransmit) #464
* included alarm ID parse to serial console (in development)
## 0.5.72
* repaired system, scheduler was not called any more #596
## 0.5.71
* improved wifi handling and tickers, many thanks to @beegee3 #571
* fixed YieldTotal correction calculation #589

2
src/app.cpp

@ -92,7 +92,7 @@ void app::loopStandard(void) {
yield();
if (ah::checkTicker(&mRxTicker, 5)) {
if (ah::checkTicker(&mRxTicker, 4)) {
bool rxRdy = mSys->Radio.switchRxCh();
if (!mSys->BufCtrl.empty()) {

1
src/app.h

@ -66,7 +66,6 @@ class app : public IApp, public ah::Scheduler {
void handleIntr(void);
void cbMqtt(char* topic, byte* payload, unsigned int length);
void saveValues(void);
void resetPayload(Inverter<>* iv);
bool getWifiApActive(void);
uint32_t getUptime() {

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 5
#define VERSION_PATCH 72
#define VERSION_PATCH 73
//-------------------------------------
typedef struct {

2
src/hm/hmDefines.h

@ -106,7 +106,7 @@ const byteAssign_t AlarmDataAssignment[] = {
};
#define HMALARMDATA_LIST_LEN (sizeof(AlarmDataAssignment) / sizeof(byteAssign_t))
#define HMALARMDATA_PAYLOAD_LEN 0 // 0: means check is off
#define ALARM_LOG_ENTRY_SIZE 12
//-------------------------------------

67
src/hm/hmInverter.h

@ -112,7 +112,6 @@ class Inverter {
uint16_t powerLimit[2]; // limit power output
float actPowerLimit; // actual power limit
uint8_t devControlCmd; // carries the requested cmd
bool devControlRequest; // true if change needed
serial_u radioId; // id converted to modbus
uint8_t channels; // number of PV channels (1-4)
record_t<REC_TYP> recordMeas; // structure for measured values
@ -121,16 +120,18 @@ class Inverter {
record_t<REC_TYP> recordAlarm; // structure for alarm values
String lastAlarmMsg;
bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null)
bool isConnected; // shows if inverter was successfully identified (fw version and hardware info)
Inverter() {
powerLimit[0] = 0xffff; // 65535 W Limit -> unlimited
powerLimit[1] = AbsolutNonPersistent; // default power limit setting
actPowerLimit = 0xffff; // init feedback from inverter to -1
devControlRequest = false;
mDevControlRequest = false;
devControlCmd = InitDataState;
initialized = false;
lastAlarmMsg = "nothing";
alarmMesIndex = 0;
isConnected = false;
}
~Inverter() {
@ -140,7 +141,7 @@ class Inverter {
template <typename T>
void enqueCommand(uint8_t cmd) {
_commandQueue.push(std::make_shared<T>(cmd));
DPRINTLN(DBG_INFO, F("(#") + String(id) + F(") enqueuedCmd: ") + String(cmd));
DPRINTLN(DBG_INFO, F("(#") + String(id) + F(") enqueuedCmd: 0x") + String(cmd, HEX));
}
void setQueuedCmdFinished() {
@ -161,10 +162,10 @@ class Inverter {
uint8_t getQueuedCmd() {
if (_commandQueue.empty()) {
if (getFwVersion() == 0)
enqueCommand<InfoCommand>(InverterDevInform_All);
enqueCommand<InfoCommand>(RealTimeRunData_Debug);
enqueCommand<InfoCommand>(InverterDevInform_All); // firmware version
enqueCommand<InfoCommand>(RealTimeRunData_Debug); // live data
if (actPowerLimit == 0xffff)
enqueCommand<InfoCommand>(SystemConfigPara);
enqueCommand<InfoCommand>(SystemConfigPara); // power limit info
}
return _commandQueue.front().get()->getCmd();
}
@ -219,6 +220,20 @@ class Inverter {
return 0;
}
bool setDevControlRequest() {
if(isConnected)
mDevControlRequest = true;
return isConnected;
}
void clearDevControlRequest() {
mDevControlRequest = false;
}
inline bool getDevControlRequest() {
return mDevControlRequest;
}
void addValue(uint8_t pos, uint8_t buf[], record_t<> *rec) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:addValue"));
if(NULL != rec) {
@ -256,11 +271,10 @@ class Inverter {
if (alarmMesIndex < rec->record[pos]){
alarmMesIndex = rec->record[pos];
//enqueCommand<InfoCommand>(AlarmUpdate); // What is the function of AlarmUpdate?
DPRINTLN(DBG_INFO, "alarm ID incremented to " + String(alarmMesIndex));
enqueCommand<InfoCommand>(AlarmData);
}
else {
alarmMesIndex = rec->record[pos]; // no change
}
}
}
else if (rec->assign == InfoAssignment) {
@ -273,6 +287,7 @@ class Inverter {
if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){
actPowerLimit = rec->record[pos];
DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit, 1));
isConnected = true;
}
}
else if (rec->assign == AlarmDataAssignment) {
@ -345,10 +360,10 @@ class Inverter {
record_t<> *getRecordStruct(uint8_t cmd) {
switch (cmd) {
case RealTimeRunData_Debug: return &recordMeas;
case InverterDevInform_All: return &recordInfo;
case SystemConfigPara: return &recordConfig;
case AlarmData: return &recordAlarm;
case RealTimeRunData_Debug: return &recordMeas; // 11 = 0x0b
case InverterDevInform_All: return &recordInfo; // 1 = 0x01
case SystemConfigPara: return &recordConfig; // 5 = 0x05
case AlarmData: return &recordAlarm; // 17 = 0x11
default: break;
}
return NULL;
@ -411,7 +426,27 @@ class Inverter {
}
}
String getAlarmStr(u_int16_t alarmCode) {
bool parseAlarmLog(uint8_t id, uint8_t pyld[], uint8_t len) {
uint8_t startOff = 2 + id * ALARM_LOG_ENTRY_SIZE;
if((startOff + ALARM_LOG_ENTRY_SIZE) > len)
return false;
uint16_t wCode = ((uint16_t)pyld[startOff]) << 8 | pyld[startOff+1];
uint32_t startTimeOffset = 0, endTimeOffset = 0;
if (((wCode >> 13) & 0x01) == 1) // check if is AM or PM
startTimeOffset = 12 * 60 * 60;
if (((wCode >> 12) & 0x01) == 1) // check if is AM or PM
endTimeOffset = 12 * 60 * 60;
uint32_t start = (((uint16_t)pyld[startOff + 4] << 8) | ((uint16_t)pyld[startOff + 5])) + startTimeOffset;
uint32_t end = (((uint16_t)pyld[startOff + 6] << 8) | ((uint16_t)pyld[startOff + 7])) + endTimeOffset;
DPRINTLN(DBG_INFO, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(end));
return true;
}
String getAlarmStr(uint16_t alarmCode) {
switch (alarmCode) { // breaks are intentionally missing!
case 1: return String(F("Inverter start"));
case 2: return String(F("DTU command failed"));
@ -486,7 +521,6 @@ class Inverter {
}
private:
std::queue<std::shared_ptr<CommandAbstract>> _commandQueue;
void toRadioId(void) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId"));
radioId.u64 = 0ULL;
@ -496,6 +530,9 @@ class Inverter {
radioId.b[1] = config->serial.b[3];
radioId.b[0] = 0x01;
}
std::queue<std::shared_ptr<CommandAbstract>> _commandQueue;
bool mDevControlRequest; // true if change needed
};

4
src/hm/hmRadio.h

@ -195,7 +195,7 @@ class HmRadio {
}
void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data) {
DPRINTLN(DBG_INFO, F("sendControlPacket cmd: ") + String(cmd));
DPRINTLN(DBG_INFO, F("sendControlPacket cmd: 0x") + String(cmd, HEX));
sendCmdPacket(invId, TX_REQ_DEVCONTROL, SINGLE_FRAME, false);
uint8_t cnt = 0;
mTxBuf[10 + cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor
@ -219,7 +219,7 @@ class HmRadio {
}
void sendTimePacket(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId) {
DPRINTLN(DBG_INFO, F("sendTimePacket ") + String(cmd, HEX));
DPRINTLN(DBG_DEBUG, F("sendTimePacket 0x") + String(cmd, HEX));
sendCmdPacket(invId, TX_REQ_INFO, ALL_FRAMES, false);
mTxBuf[10] = cmd; // cid
mTxBuf[11] = 0x00;

131
src/hm/payload.h

@ -24,6 +24,7 @@ typedef struct {
bool lastFound;
uint8_t retransmits;
bool requested;
bool gotFragment;
} invPayload_t;
@ -41,7 +42,9 @@ class Payload : public Handler<payloadListenerType> {
mStat = stat;
mMaxRetrans = maxRetransmits;
mTimestamp = timestamp;
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
reset(i);
}
mSerialDebug = false;
mHighPrioIv = NULL;
}
@ -69,14 +72,15 @@ class Payload : public Handler<payloadListenerType> {
void ivSend(Inverter<> *iv, bool highPrio = false) {
if(!highPrio) {
if (mPayload[iv->id].requested) {
if (!mPayload[iv->id].complete)
process(false);
process(false); // no retransmit
if (!mPayload[iv->id].complete) {
if (0 == mPayload[iv->id].maxPackId)
mStat->rxFailNoAnser++;
if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId)
mStat->rxFailNoAnser++; // got nothing
else
mStat->rxFail++;
mStat->rxFail++; // got fragments but not complete response
iv->setQueuedCmdFinished(); // command failed
if (mSerialDebug)
@ -87,24 +91,25 @@ class Payload : public Handler<payloadListenerType> {
}
}
}
}
reset(iv);
reset(iv->id);
mPayload[iv->id].requested = true;
yield();
if (mSerialDebug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX));
if (iv->devControlRequest) {
if (iv->getDevControlRequest()) {
if (mSerialDebug)
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request 0x") + String(iv->devControlCmd, HEX) + F(" power limit ") + String(iv->powerLimit[0]));
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
mPayload[iv->id].txCmd = iv->devControlCmd;
iv->clearCmdQueue();
iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
//iv->clearCmdQueue();
//iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
} else {
uint8_t cmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket"));
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket")); // + String(cmd, HEX));
mSys->Radio.sendTimePacket(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex);
mPayload[iv->id].txCmd = cmd;
}
@ -112,7 +117,11 @@ class Payload : public Handler<payloadListenerType> {
void add(packet_t *p, uint8_t len) {
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
if ((NULL != iv) && (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES))) { // response from get information command
if(NULL == iv)
return;
if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
mPayload[iv->id].txId = p->packet[0];
DPRINTLN(DBG_DEBUG, F("Response from info request received"));
uint8_t *pid = &p->packet[9];
@ -120,26 +129,26 @@ class Payload : public Handler<payloadListenerType> {
DPRINT(DBG_DEBUG, F("fragment number zero received and ignored"));
} else {
DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX));
if ((*pid & 0x7F) < 5) {
if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) {
memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], len - 11);
mPayload[iv->id].len[(*pid & 0x7F) - 1] = len - 11;
mPayload[iv->id].gotFragment = true;
}
if ((*pid & ALL_FRAMES) == ALL_FRAMES) {
// Last packet
if ((*pid & 0x7f) > mPayload[iv->id].maxPackId) {
if (((*pid & 0x7f) > mPayload[iv->id].maxPackId) || (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId)) {
mPayload[iv->id].maxPackId = (*pid & 0x7f);
if (*pid > 0x81)
mPayload[iv->id].lastFound = true;
}
}
}
}
if ((NULL != iv) && (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES))) { // response from dev control command
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received"));
mPayload[iv->id].txId = p->packet[0];
iv->devControlRequest = false;
iv->clearDevControlRequest();
if ((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00)) {
String msg = "";
@ -148,31 +157,13 @@ class Payload : public Handler<payloadListenerType> {
else
msg = "NOT ";
DPRINTLN(DBG_INFO, F("Inverter ") + String(iv->id) + F(" has ") + msg + F("accepted power limit set point ") + String(iv->powerLimit[0]) + F(" with PowerLimitControl ") + String(iv->powerLimit[1]));
iv->clearCmdQueue();
iv->enqueCommand<InfoCommand>(SystemConfigPara); // read back power limit
}
iv->devControlCmd = Init;
}
}
bool build(uint8_t id) {
DPRINTLN(DBG_VERBOSE, F("build"));
uint16_t crc = 0xffff, crcRcv = 0x0000;
if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES)
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) {
if (mPayload[id].len[i] > 0) {
if (i == (mPayload[id].maxPackId - 1)) {
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc);
crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]);
} else
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc);
}
yield();
}
return (crc == crcRcv) ? true : false;
}
void process(bool retransmit) {
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
@ -182,6 +173,7 @@ class Payload : public Handler<payloadListenerType> {
if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) {
// no processing needed if txId is not 0x95
mPayload[iv->id].complete = true;
continue; // skip to next inverter
}
if (!mPayload[iv->id].complete) {
@ -191,18 +183,21 @@ class Payload : public Handler<payloadListenerType> {
// This is required to prevent retransmissions without answer.
DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm..."));
mPayload[iv->id].retransmits = mMaxRetrans;
} else if(iv->devControlCmd == ActivePowerContr) {
DPRINTLN(DBG_INFO, F("retransmit power limit"));
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
} else {
if (mPayload[iv->id].retransmits < mMaxRetrans) {
mPayload[iv->id].retransmits++;
if(false == mPayload[iv->id].lastFound) {
DPRINTLN(DBG_WARN, F("while retrieving data: last frame missing: Request Complete Retransmit"));
if(false == mPayload[iv->id].gotFragment) {
DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit"));
mPayload[iv->id].txCmd = iv->getQueuedCmd();
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket"));
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") sendTimePacket 0x") + String(mPayload[iv->id].txCmd, HEX));
mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex);
} else {
for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) {
if (mPayload[iv->id].len[i] == 0) {
DPRINTLN(DBG_WARN, F("while retrieving data: Frame ") + String(i + 1) + F(" missing: Request Retransmit"));
DPRINTLN(DBG_WARN, F("Frame ") + String(i + 1) + F(" missing: Request Retransmit"));
mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true);
break; // only request retransmit one frame per loop
}
@ -214,7 +209,7 @@ class Payload : public Handler<payloadListenerType> {
}
}
} else { // payload complete
DPRINTLN(DBG_INFO, F("procPyld: cmd: ") + String(mPayload[iv->id].txCmd));
DPRINTLN(DBG_INFO, F("procPyld: cmd: 0x") + String(mPayload[iv->id].txCmd, HEX));
DPRINTLN(DBG_INFO, F("procPyld: txid: 0x") + String(mPayload[iv->id].txId, HEX));
DPRINTLN(DBG_DEBUG, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId));
record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser
@ -250,6 +245,15 @@ class Payload : public Handler<payloadListenerType> {
}
iv->doCalculations();
notify(mPayload[iv->id].txCmd);
if(AlarmData == mPayload[iv->id].txCmd) {
uint8_t i = 0;
while(1) {
if(!iv->parseAlarmLog(i++, payload, payloadLen))
break;
yield();
}
}
} else {
DPRINTLN(DBG_ERROR, F("plausibility check failed, expected ") + String(rec->pyldLen) + F(" bytes"));
mStat->rxFail++;
@ -264,19 +268,40 @@ class Payload : public Handler<payloadListenerType> {
}
}
void reset(Inverter<> *iv) {
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id));
memset(mPayload[iv->id].len, 0, MAX_PAYLOAD_ENTRIES);
mPayload[iv->id].txCmd = 0;
mPayload[iv->id].retransmits = 0;
mPayload[iv->id].maxPackId = 0;
mPayload[iv->id].lastFound = false;
mPayload[iv->id].complete = false;
mPayload[iv->id].requested = false;
mPayload[iv->id].ts = *mTimestamp;
private:
bool build(uint8_t id) {
DPRINTLN(DBG_VERBOSE, F("build"));
uint16_t crc = 0xffff, crcRcv = 0x0000;
if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES)
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) {
if (mPayload[id].len[i] > 0) {
if (i == (mPayload[id].maxPackId - 1)) {
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc);
crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]);
} else
crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc);
}
yield();
}
return (crc == crcRcv) ? true : false;
}
void reset(uint8_t id) {
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(id));
memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES);
mPayload[id].txCmd = 0;
mPayload[id].gotFragment = false;
mPayload[id].retransmits = 0;
mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES;
mPayload[id].lastFound = false;
mPayload[id].complete = false;
mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp;
}
private:
IApp *mApp;
HMSYSTEM *mSys;
statistics_t *mStat;

8
src/publisher/pubMqtt.h

@ -148,10 +148,10 @@ class PubMqtt {
if(!mClient.connected())
return;
char topic[(MQTT_TOPIC_LEN << 1) + 2];
snprintf(topic, ((MQTT_TOPIC_LEN << 1) + 2), "%s/%s", mCfgMqtt->topic, subTopic);
if(addTopic)
mClient.publish(topic, QOS_0, retained, payload);
if(addTopic) {
String topic = String(mCfgMqtt->topic) + "/" + String(subTopic);
mClient.publish(topic.c_str(), QOS_0, retained, payload);
}
else
mClient.publish(subTopic, QOS_0, retained, payload);
mTxCnt++;

9
src/utils/helper.cpp

@ -40,6 +40,15 @@ namespace ah {
return String(str);
}
String getTimeStr(time_t t) {
char str[9];
if(0 == t)
sprintf(str, "n/a");
else
sprintf(str, "%02d:%02d:%02d", hour(t), minute(t), second(t));
return String(str);
}
uint64_t Serial2u64(const char *val) {
char tmp[3];
uint64_t ret = 0ULL;

1
src/utils/helper.h

@ -21,6 +21,7 @@ namespace ah {
void ip2Char(uint8_t ip[], char *str);
double round3(double value);
String getDateTimeStr(time_t t);
String getTimeStr(time_t t);
uint64_t Serial2u64(const char *val);
}

15
src/web/RestApi.h

@ -20,6 +20,7 @@ class RestApi {
RestApi() {
mTimezoneOffset = 0;
mFreeHeap = 0;
nr = 0;
}
void setup(IApp *app, HMSYSTEM *sys, AsyncWebServer *srv, settings_t *config) {
@ -539,6 +540,7 @@ class RestApi {
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut) {
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
bool accepted = true;
if(NULL == iv) {
jsonOut[F("error")] = F("inverter index invalid: ") + jsonIn[F("id")].as<String>();
return false;
@ -546,10 +548,10 @@ class RestApi {
if(F("power") == jsonIn[F("cmd")]) {
iv->devControlCmd = (jsonIn[F("val")] == 1) ? TurnOn : TurnOff;
iv->devControlRequest = true;
accepted = iv->setDevControlRequest();
} else if(F("restart") == jsonIn[F("restart")]) {
iv->devControlCmd = Restart;
iv->devControlRequest = true;
accepted = iv->setDevControlRequest();
}
else if(0 == strncmp("limit_", jsonIn[F("cmd")].as<const char*>(), 6)) {
iv->powerLimit[0] = jsonIn["val"];
@ -562,7 +564,8 @@ class RestApi {
else if(F("limit_nonpersistent_absolute") == jsonIn[F("cmd")])
iv->powerLimit[1] = AbsolutNonPersistent;
iv->devControlCmd = ActivePowerContr;
iv->devControlRequest = true;
accepted = iv->setDevControlRequest();
if(accepted)
mApp->ivSendHighPrio(iv);
}
else if(F("dev") == jsonIn[F("cmd")]) {
@ -574,6 +577,11 @@ class RestApi {
return false;
}
if(!accepted) {
jsonOut[F("error")] = F("inverter does not accept dev control request at this moment");
return false;
}
return true;
}
@ -605,6 +613,7 @@ class RestApi {
uint32_t mTimezoneOffset;
uint32_t mFreeHeap;
uint16_t nr;
};
#endif /*__WEB_API_H__*/

6
src/web/web.h

@ -71,7 +71,7 @@ class Web {
mWeb.on("/save", HTTP_ANY, std::bind(&Web::showSave, this, std::placeholders::_1));
mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1));
mWeb.on("/api1", HTTP_POST, std::bind(&Web::showWebApi, this, std::placeholders::_1));
//mWeb.on("/api1", HTTP_POST, std::bind(&Web::showWebApi, this, std::placeholders::_1));
#ifdef ENABLE_JSON_EP
mWeb.on("/json", HTTP_ANY, std::bind(&Web::showJson, this, std::placeholders::_1));
@ -584,7 +584,7 @@ class Web {
request->send(response);
}
void showWebApi(AsyncWebServerRequest *request) {
/*void showWebApi(AsyncWebServerRequest *request) {
// TODO: remove
DPRINTLN(DBG_VERBOSE, F("web::showWebApi"));
DPRINTLN(DBG_DEBUG, request->arg("plain"));
@ -647,7 +647,7 @@ class Web {
}
}
request->send(200, "text/json", "{success:true}");
}
}*/
void onSerial(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onSerial"));

Loading…
Cancel
Save