BREAKING CHANGE: Structure WebAPI /api/livedata/status changed

The different inverter data are now in a subobject called "inverters".
This is required to extend the API by other data then the inverter values
This commit is contained in:
Thomas Basler 2022-11-01 15:04:05 +01:00
parent f854cdff03
commit 69b675bc64
4 changed files with 45 additions and 37 deletions

View File

@ -13,7 +13,7 @@ public:
private:
void generateJsonResponse(JsonVariant& root);
void addField(JsonVariant& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic = "");
void addField(JsonObject& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic = "");
void onLivedataStatus(AsyncWebServerRequest* request);
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);

View File

@ -73,48 +73,51 @@ void WebApiWsLiveClass::loop()
void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
{
JsonArray invArray = root.createNestedArray("inverters");
// Loop all inverters
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
auto inv = Hoymiles.getInverterByPos(i);
root[i][F("serial")] = inv->serialString();
root[i][F("name")] = inv->name();
root[i][F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
root[i][F("reachable")] = inv->isReachable();
root[i][F("producing")] = inv->isProducing();
root[i][F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
JsonObject invObject = invArray.createNestedObject();
invObject[F("serial")] = inv->serialString();
invObject[F("name")] = inv->name();
invObject[F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
invObject[F("reachable")] = inv->isReachable();
invObject[F("producing")] = inv->isProducing();
invObject[F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
if (inv->DevInfo()->getMaxPower() > 0) {
root[i][F("limit_absolute")] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
invObject[F("limit_absolute")] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
} else {
root[i][F("limit_absolute")] = -1;
invObject[F("limit_absolute")] = -1;
}
// Loop all channels
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
addField(root, i, inv, c, FLD_PAC);
addField(root, i, inv, c, FLD_UAC);
addField(root, i, inv, c, FLD_IAC);
addField(invObject, i, inv, c, FLD_PAC);
addField(invObject, i, inv, c, FLD_UAC);
addField(invObject, i, inv, c, FLD_IAC);
if (c == 0) {
addField(root, i, inv, c, FLD_PDC, F("Power DC"));
addField(invObject, i, inv, c, FLD_PDC, F("Power DC"));
} else {
addField(root, i, inv, c, FLD_PDC);
addField(invObject, i, inv, c, FLD_PDC);
}
addField(root, i, inv, c, FLD_UDC);
addField(root, i, inv, c, FLD_IDC);
addField(root, i, inv, c, FLD_YD);
addField(root, i, inv, c, FLD_YT);
addField(root, i, inv, c, FLD_F);
addField(root, i, inv, c, FLD_T);
addField(root, i, inv, c, FLD_PF);
addField(root, i, inv, c, FLD_PRA);
addField(root, i, inv, c, FLD_EFF);
addField(root, i, inv, c, FLD_IRR);
addField(invObject, i, inv, c, FLD_UDC);
addField(invObject, i, inv, c, FLD_IDC);
addField(invObject, i, inv, c, FLD_YD);
addField(invObject, i, inv, c, FLD_YT);
addField(invObject, i, inv, c, FLD_F);
addField(invObject, i, inv, c, FLD_T);
addField(invObject, i, inv, c, FLD_PF);
addField(invObject, i, inv, c, FLD_PRA);
addField(invObject, i, inv, c, FLD_EFF);
addField(invObject, i, inv, c, FLD_IRR);
}
if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) {
root[i][F("events")] = inv->EventLog()->getEntryCount();
invObject[F("events")] = inv->EventLog()->getEntryCount();
} else {
root[i][F("events")] = -1;
invObject[F("events")] = -1;
}
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
@ -123,7 +126,7 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
}
}
void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic)
void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic)
{
if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) {
String chanName;
@ -132,9 +135,9 @@ void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr
} else {
chanName = topic;
}
root[idx][String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
root[idx][String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
root[idx][String(channel)][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(channel, fieldId);
root[String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
root[String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
root[String(channel)][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(channel, fieldId);
}
}
@ -153,8 +156,8 @@ void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketC
void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
{
AsyncJsonResponse* response = new AsyncJsonResponse(true, 40960U);
JsonVariant root = response->getRoot().as<JsonVariant>();
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
JsonVariant root = response->getRoot();
generateJsonResponse(root);

View File

@ -31,4 +31,6 @@ export interface Inverter {
[key: number]: InverterStatistics,
};
export interface Inverters extends Array<Inverter>{};
export interface LiveData {
inverters: Inverter[],
}

View File

@ -332,7 +332,7 @@ import BootstrapAlert from '@/components/BootstrapAlert.vue';
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
import type { DevInfoStatus } from '@/types/DevInfoStatus';
import type { EventlogItems } from '@/types/EventlogStatus';
import type { Inverters } from '@/types/LiveDataStatus';
import type { LiveData, Inverter } from '@/types/LiveDataStatus';
import type { LimitStatus } from '@/types/LimitStatus';
import type { LimitConfig } from '@/types/LimitConfig';
import { formatNumber } from '@/utils';
@ -361,7 +361,7 @@ export default defineComponent({
heartInterval: 0,
dataAgeInterval: 0,
dataLoading: true,
inverterData: [] as Inverters,
liveData: {} as LiveData,
isFirstFetchAfterConnect: true,
eventLogView: {} as bootstrap.Modal,
eventLogList: {} as EventlogItems,
@ -435,6 +435,9 @@ export default defineComponent({
},
currentLimitRelative(): string {
return formatNumber(this.currentLimitList.limit_relative, 2);
},
inverterData(): Inverter[] {
return this.liveData.inverters;
}
},
methods: {
@ -444,7 +447,7 @@ export default defineComponent({
fetch("/api/livedata/status")
.then((response) => response.json())
.then((data) => {
this.inverterData = data;
this.liveData = data;
this.dataLoading = false;
});
},
@ -459,7 +462,7 @@ export default defineComponent({
this.socket.onmessage = (event) => {
console.log(event);
this.inverterData = JSON.parse(event.data);
this.liveData = JSON.parse(event.data);
this.dataLoading = false;
this.heartCheck(); // Reset heartbeat detection
};