Browse Source

* improved records in hmInverter

* added records to api
* removed unused endpoints from api
pull/283/head
lumapu 2 years ago
parent
commit
66b70f24e5
  1. 85
      tools/esp8266/app.cpp
  2. 23
      tools/esp8266/hmInverter.h
  3. 4
      tools/esp8266/hmRadio.h
  4. 27
      tools/esp8266/webApi.cpp
  5. 1
      tools/esp8266/webApi.h

85
tools/esp8266/app.cpp

@ -94,26 +94,22 @@ void app::loop(void) {
if(0 != len) {
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
if(NULL != iv && p->packet[0] == (TX_REQ_INFO + 0x80)) { // response from get information command
if((NULL != iv) && (p->packet[0] == (TX_REQ_INFO + 0x80))) { // 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];
if (*pid == 0x00)
{
DPRINT(DBG_DEBUG, "fragment number zero received and ignored");
}
else
{
if ((*pid & 0x7F) < 5)
{
else {
DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX));
if ((*pid & 0x7F) < 5) {
memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], len - 11);
mPayload[iv->id].len[(*pid & 0x7F) - 1] = len - 11;
}
if ((*pid & 0x80) == 0x80)
{ // Last packet
if ((*pid & 0x7f) > mPayload[iv->id].maxPackId)
{
if ((*pid & 0x80) == 0x80) {
// Last packet
if ((*pid & 0x7f) > mPayload[iv->id].maxPackId) {
mPayload[iv->id].maxPackId = (*pid & 0x7f);
if (*pid > 0x81)
mLastPacketId = *pid;
@ -121,7 +117,7 @@ void app::loop(void) {
}
}
}
if(NULL != iv && p->packet[0] == (TX_REQ_DEVCONTROL + 0x80)) { // response from dev control command
if((NULL != iv) && (p->packet[0] == (TX_REQ_DEVCONTROL + 0x80))) { // response from dev control command
mPayload[iv->id].txId = p->packet[0];
DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received"));
iv->devControlRequest = false;
@ -225,11 +221,13 @@ void app::loop(void) {
int8_t maxLoop = MAX_NUM_INVERTERS;
Inverter<> *iv = mSys->getInverterByPos(mSendLastIvId);
do {
if(NULL != iv)
mPayload[iv->id].requested = false;
//if(NULL != iv)
// mPayload[iv->id].requested = false;
mSendLastIvId = ((MAX_NUM_INVERTERS-1) == mSendLastIvId) ? 0 : mSendLastIvId + 1;
iv = mSys->getInverterByPos(mSendLastIvId);
} while((NULL == iv) && ((maxLoop--) > 0));
resetPayload(iv);
mPayload[iv->id].requested = true;
if(NULL != iv) {
if(!mPayload[iv->id].complete)
@ -247,8 +245,6 @@ void app::loop(void) {
}
}
resetPayload(iv);
yield();
if(mConfig.serialDebug) {
DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status()));
@ -316,12 +312,13 @@ void app::processPayload(bool retransmit) {
boolean doMQTT = false;
#endif
DPRINTLN(DBG_VERBOSE, F("app::processPayload"));
//DPRINTLN(DBG_INFO, F("processPayload"));
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL != iv) {
if(mPayload[iv->id].txId != (TX_REQ_INFO + 0x80)) {
// no processing needed if txId is not 0x95
DPRINTLN(DBG_DEBUG, F("processPayload - set complete"));
mPayload[iv->id].complete = true;
}
if(!mPayload[iv->id].complete ) {
@ -334,7 +331,7 @@ void app::processPayload(bool retransmit) {
for(uint8_t i = 0; i < (mPayload[iv->id].maxPackId-1); i ++) {
if(mPayload[iv->id].len[i] == 0) {
if(mConfig.serialDebug)
DPRINTLN(DBG_ERROR, F("while retrieving data: Frame ") + String(i+1) + F(" missing: Request Retransmit"));
DPRINTLN(DBG_WARN, F("while retrieving data: Frame ") + String(i+1) + F(" missing: Request Retransmit"));
mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME+i), true);
break; // only retransmit one frame per loop
}
@ -343,12 +340,14 @@ void app::processPayload(bool retransmit) {
}
else {
if(mConfig.serialDebug)
DPRINTLN(DBG_ERROR, F("while retrieving data: last frame missing: Request Retransmit"));
//if(0x00 != mLastPacketId)
// mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true);
//else
DPRINTLN(DBG_WARN, F("while retrieving data: last frame missing: Request Retransmit"));
if(0x00 != mLastPacketId)
mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, mLastPacketId, true);
else {
mPayload[iv->id].txCmd = iv->getQueuedCmd();
mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex);
}
}
mSys->Radio.switchRxCh(100);
}
}
@ -356,14 +355,12 @@ void app::processPayload(bool retransmit) {
}
else { // payload complete
DPRINTLN(DBG_INFO, F("procPyld: cmd: ") + String(mPayload[iv->id].txCmd));
DPRINTLN(DBG_INFO, F("procPyld: txid: ") + String(mPayload[iv->id].txId));
DPRINTLN(DBG_INFO, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId));
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
if(NULL == rec)
DPRINTLN(DBG_ERROR, F("record is NULL!"));
mPayload[iv->id].complete = true;
rec->ts = mPayload[iv->id].ts;
mStat.rxSuccess++;
uint8_t payload[128];
uint8_t offs = 0;
@ -380,28 +377,31 @@ void app::processPayload(bool retransmit) {
mSys->Radio.dumpBuf(NULL, payload, offs);
}
if(NULL == rec)
DPRINTLN(DBG_ERROR, F("record is NULL!"));
else {
rec->ts = mPayload[iv->id].ts;
for(uint8_t i = 0; i < rec->length; i++) {
iv->addValue(i, payload, rec);
yield();
}
iv->doCalculations();
iv->setQueuedCmdFinished();
// MQTT send out
if(mMqttActive) {
record_t<> *recRealtime = iv->getRecordStruct(RealTimeRunData_Debug);
char topic[30], val[10];
float total[4];
memset(total, 0, sizeof(float) * 4);
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) {
if(iv->getRecordStruct(RealTimeRunData_Debug) == rec) {
if (iv->isAvailable(mTimestamp, rec)) {
for (uint8_t i = 0; i < rec->length; i++) {
snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
snprintf(val, 10, "%.3f", iv->getValue(i, rec));
mMqtt.sendMsg(topic, val);
if(recRealtime == rec) {
if(CH0 == rec->assign[i].ch) {
switch(rec->assign[i].fieldId) {
case FLD_PAC: total[0] += iv->getValue(i, rec); break;
@ -410,14 +410,15 @@ void app::processPayload(bool retransmit) {
case FLD_PDC: total[3] += iv->getValue(i, rec); break;
}
}
yield();
}
yield();
}
}
}
}
// total values (sum of all inverters)
if(recRealtime == rec) {
if(mSys->getNumInverters() > 1) {
uint8_t fieldId = 0;
for (uint8_t i = 0; i < 4; i++) {
@ -433,8 +434,12 @@ void app::processPayload(bool retransmit) {
}
}
}
}
}
resetPayload(iv);
iv->setQueuedCmdFinished();
//resetPayload(iv);
#ifdef __MQTT_AFTER_RX__
doMQTT = true;
@ -657,12 +662,7 @@ void app::resetSystem(void) {
mShowRebootRequest = false;
Inverter<> *iv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
iv = mSys->getInverterByPos(i, false);
if(NULL != iv)
resetPayload(iv);
}
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
memset(&mStat, 0, sizeof(statistics_t));
mLastPacketId = 0x00;
}
@ -757,6 +757,12 @@ void app::loadEEpconfig(void) {
mMqttInterval += mConfig.sendInterval;
}
}
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
iv = mSys->getInverterByPos(i, false);
if(NULL != iv)
resetPayload(iv);
}
}
}
@ -825,11 +831,12 @@ void app::setupMqtt(void) {
//-----------------------------------------------------------------------------
void app::resetPayload(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].complete = false;
mPayload[iv->id].requested = true;
mPayload[iv->id].requested = false;
mPayload[iv->id].ts = mTimestamp;
}

23
tools/esp8266/hmInverter.h

@ -203,6 +203,10 @@ class Inverter {
return 0xff;
}
byteAssign_t *getByteAssign(uint8_t pos, record_t<> *rec) {
return &rec->assign[pos];
}
const char *getFieldName(uint8_t pos, record_t<> *rec) {
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:getFieldName"));
if(NULL != rec)
@ -230,7 +234,8 @@ class Inverter {
uint8_t ptr = rec->assign[pos].start;
uint8_t end = ptr + rec->assign[pos].num;
uint16_t div = rec->assign[pos].div;
if(rec == &recordMeas) {
if(NULL != rec) {
if(CMD_CALC != div) {
uint32_t val = 0;
do {
@ -242,6 +247,11 @@ class Inverter {
else
rec->record[pos] = (REC_TYP)(val);
}
}
if(rec == &recordMeas) {
DPRINTLN(DBG_VERBOSE, "add real time");
// get last alarm message index and save it in the inverter object
if (getPosByChFld(0, FLD_ALARM_MES_ID, rec) == pos){
if (alarmMesIndex < rec->record[pos]){
@ -254,25 +264,30 @@ class Inverter {
}
}
}
if (rec == &recordInfo) {
else if (rec->assign == InfoAssignment) {
DPRINTLN(DBG_INFO, "add info");
// get at least the firmware version and save it to the inverter object
if (getPosByChFld(0, FLD_FW_VERSION, rec) == pos){
fwVersion = rec->record[pos];
DPRINT(DBG_DEBUG, F("Inverter FW-Version: ") + String(fwVersion));
}
}
if (rec == &recordConfig) {
else if (rec->assign == SystemConfigParaAssignment) {
DPRINTLN(DBG_INFO, "add config");
// get at least the firmware version and save it to the inverter object
if (getPosByChFld(0, FLD_ACT_PWR_LIMIT, rec) == pos){
actPowerLimit = rec->record[pos];
DPRINT(DBG_DEBUG, F("Inverter actual power limit: ") + String(actPowerLimit));
}
}
if (rec == &recordAlarm){
else if (rec->assign == AlarmDataAssignment) {
DPRINTLN(DBG_INFO, "add alarm");
if (getPosByChFld(0, FLD_LAST_ALARM_CODE, rec) == pos){
lastAlarmMsg = getAlarmStr(rec->record[pos]);
}
}
else
DPRINTLN(DBG_WARN, F("add with unknown assginment"));
}
else
DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x"));

4
tools/esp8266/hmRadio.h

@ -164,7 +164,7 @@ class HmRadio {
}
void sendControlPacket(uint64_t invId, uint8_t cmd, uint16_t *data) {
DPRINTLN(DBG_INFO, F("sendControlPacket"));
DPRINTLN(DBG_INFO, F("sendControlPacket cmd: ") + String(cmd));
sendCmdPacket(invId, TX_REQ_DEVCONTROL, ALL_FRAMES, false); // 0x80 implementation as original DTU code
int cnt = 0;
mTxBuf[10] = cmd; // cmd --> 0x0b => Type_ActivePowerContr, 0 on, 1 off, 2 restart, 12 reactive power, 13 power factor
@ -205,7 +205,7 @@ class HmRadio {
}
void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool calcCrc = true) {
DPRINTLN(DBG_INFO, F("sendCmdPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX));
DPRINTLN(DBG_VERBOSE, F("sendCmdPacket, mid: ") + String(mid, HEX) + F(" pid: ") + String(pid, HEX));
memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE);
mTxBuf[0] = mid; // message id
CP_U32_BigEndian(&mTxBuf[1], (invId >> 8));

27
tools/esp8266/webApi.cpp

@ -39,6 +39,7 @@ void webApi::onApi(AsyncWebServerRequest *request) {
AsyncJsonResponse* response = new AsyncJsonResponse(false, 2048);
JsonObject root = response->getRoot();
Inverter<> *iv = mApp->mSys->getInverterByPos(0, false);
String path = request->url().substring(5);
if(path == "system") getSystem(root);
else if(path == "statistics") getStatistics(root);
@ -46,6 +47,10 @@ void webApi::onApi(AsyncWebServerRequest *request) {
else if(path == "index") getIndex(root);
else if(path == "setup") getSetup(root);
else if(path == "live") getLive(root);
else if(path == "record/info") getRecord(root, iv->getRecordStruct(InverterDevInform_All));
else if(path == "record/alarm") getRecord(root, iv->getRecordStruct(AlarmData));
else if(path == "record/config") getRecord(root, iv->getRecordStruct(SystemConfigPara));
else if(path == "record/live") getRecord(root, iv->getRecordStruct(RealTimeRunData_Debug));
else
getNotFound(root, F("http://") + request->host() + F("/api/"));
@ -301,6 +306,28 @@ void webApi::getLive(JsonObject obj) {
}
//-----------------------------------------------------------------------------
void webApi::getRecord(JsonObject obj, record_t<> *rec) {
JsonArray invArr = obj.createNestedArray(F("inverter"));
Inverter<> *iv;
uint8_t pos;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
iv = mApp->mSys->getInverterByPos(i);
if(NULL != iv) {
JsonArray obj2 = invArr.createNestedArray();
for(uint8_t j = 0; j < rec->length; j++) {
byteAssign_t *assign = iv->getByteAssign(j, rec);
pos = (iv->getPosByChFld(assign->ch, assign->fieldId, rec));
obj2[j]["fld"] = (0xff != pos) ? String(iv->getFieldName(pos, rec)) : F("n/a");
obj2[j]["unit"] = (0xff != pos) ? String(iv->getUnit(pos, rec)) : F("n/a");
obj2[j]["val"] = (0xff != pos) ? String(iv->getValue(pos, rec)) : F("n/a");
}
}
}
}
//-----------------------------------------------------------------------------
bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) {
uint8_t cmd = jsonIn[F("cmd")];

1
tools/esp8266/webApi.h

@ -35,6 +35,7 @@ class webApi {
void getIndex(JsonObject obj);
void getSetup(JsonObject obj);
void getLive(JsonObject obj);
void getRecord(JsonObject obj, record_t<> *rec);
bool setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut);

Loading…
Cancel
Save