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:
parent
f854cdff03
commit
69b675bc64
@ -13,7 +13,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root);
|
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 onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|
||||||
|
|||||||
@ -73,48 +73,51 @@ void WebApiWsLiveClass::loop()
|
|||||||
|
|
||||||
void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||||
{
|
{
|
||||||
|
JsonArray invArray = root.createNestedArray("inverters");
|
||||||
// Loop all inverters
|
// Loop all inverters
|
||||||
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
||||||
auto inv = Hoymiles.getInverterByPos(i);
|
auto inv = Hoymiles.getInverterByPos(i);
|
||||||
|
|
||||||
root[i][F("serial")] = inv->serialString();
|
JsonObject invObject = invArray.createNestedObject();
|
||||||
root[i][F("name")] = inv->name();
|
|
||||||
root[i][F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
invObject[F("serial")] = inv->serialString();
|
||||||
root[i][F("reachable")] = inv->isReachable();
|
invObject[F("name")] = inv->name();
|
||||||
root[i][F("producing")] = inv->isProducing();
|
invObject[F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
||||||
root[i][F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
|
invObject[F("reachable")] = inv->isReachable();
|
||||||
|
invObject[F("producing")] = inv->isProducing();
|
||||||
|
invObject[F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
|
||||||
if (inv->DevInfo()->getMaxPower() > 0) {
|
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 {
|
} else {
|
||||||
root[i][F("limit_absolute")] = -1;
|
invObject[F("limit_absolute")] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop all channels
|
// Loop all channels
|
||||||
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
|
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
|
||||||
addField(root, i, inv, c, FLD_PAC);
|
addField(invObject, i, inv, c, FLD_PAC);
|
||||||
addField(root, i, inv, c, FLD_UAC);
|
addField(invObject, i, inv, c, FLD_UAC);
|
||||||
addField(root, i, inv, c, FLD_IAC);
|
addField(invObject, i, inv, c, FLD_IAC);
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
addField(root, i, inv, c, FLD_PDC, F("Power DC"));
|
addField(invObject, i, inv, c, FLD_PDC, F("Power DC"));
|
||||||
} else {
|
} else {
|
||||||
addField(root, i, inv, c, FLD_PDC);
|
addField(invObject, i, inv, c, FLD_PDC);
|
||||||
}
|
}
|
||||||
addField(root, i, inv, c, FLD_UDC);
|
addField(invObject, i, inv, c, FLD_UDC);
|
||||||
addField(root, i, inv, c, FLD_IDC);
|
addField(invObject, i, inv, c, FLD_IDC);
|
||||||
addField(root, i, inv, c, FLD_YD);
|
addField(invObject, i, inv, c, FLD_YD);
|
||||||
addField(root, i, inv, c, FLD_YT);
|
addField(invObject, i, inv, c, FLD_YT);
|
||||||
addField(root, i, inv, c, FLD_F);
|
addField(invObject, i, inv, c, FLD_F);
|
||||||
addField(root, i, inv, c, FLD_T);
|
addField(invObject, i, inv, c, FLD_T);
|
||||||
addField(root, i, inv, c, FLD_PF);
|
addField(invObject, i, inv, c, FLD_PF);
|
||||||
addField(root, i, inv, c, FLD_PRA);
|
addField(invObject, i, inv, c, FLD_PRA);
|
||||||
addField(root, i, inv, c, FLD_EFF);
|
addField(invObject, i, inv, c, FLD_EFF);
|
||||||
addField(root, i, inv, c, FLD_IRR);
|
addField(invObject, i, inv, c, FLD_IRR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) {
|
if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) {
|
||||||
root[i][F("events")] = inv->EventLog()->getEntryCount();
|
invObject[F("events")] = inv->EventLog()->getEntryCount();
|
||||||
} else {
|
} else {
|
||||||
root[i][F("events")] = -1;
|
invObject[F("events")] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
|
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)) {
|
if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) {
|
||||||
String chanName;
|
String chanName;
|
||||||
@ -132,9 +135,9 @@ void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr
|
|||||||
} else {
|
} else {
|
||||||
chanName = topic;
|
chanName = topic;
|
||||||
}
|
}
|
||||||
root[idx][String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
|
root[String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
|
||||||
root[idx][String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
|
root[String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
|
||||||
root[idx][String(channel)][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(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)
|
void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(true, 40960U);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
|
||||||
JsonVariant root = response->getRoot().as<JsonVariant>();
|
JsonVariant root = response->getRoot();
|
||||||
|
|
||||||
generateJsonResponse(root);
|
generateJsonResponse(root);
|
||||||
|
|
||||||
|
|||||||
@ -31,4 +31,6 @@ export interface Inverter {
|
|||||||
[key: number]: InverterStatistics,
|
[key: number]: InverterStatistics,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Inverters extends Array<Inverter>{};
|
export interface LiveData {
|
||||||
|
inverters: Inverter[],
|
||||||
|
}
|
||||||
@ -332,7 +332,7 @@ import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
|||||||
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
|
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
|
||||||
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
||||||
import type { EventlogItems } from '@/types/EventlogStatus';
|
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 { LimitStatus } from '@/types/LimitStatus';
|
||||||
import type { LimitConfig } from '@/types/LimitConfig';
|
import type { LimitConfig } from '@/types/LimitConfig';
|
||||||
import { formatNumber } from '@/utils';
|
import { formatNumber } from '@/utils';
|
||||||
@ -361,7 +361,7 @@ export default defineComponent({
|
|||||||
heartInterval: 0,
|
heartInterval: 0,
|
||||||
dataAgeInterval: 0,
|
dataAgeInterval: 0,
|
||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
inverterData: [] as Inverters,
|
liveData: {} as LiveData,
|
||||||
isFirstFetchAfterConnect: true,
|
isFirstFetchAfterConnect: true,
|
||||||
eventLogView: {} as bootstrap.Modal,
|
eventLogView: {} as bootstrap.Modal,
|
||||||
eventLogList: {} as EventlogItems,
|
eventLogList: {} as EventlogItems,
|
||||||
@ -435,6 +435,9 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
currentLimitRelative(): string {
|
currentLimitRelative(): string {
|
||||||
return formatNumber(this.currentLimitList.limit_relative, 2);
|
return formatNumber(this.currentLimitList.limit_relative, 2);
|
||||||
|
},
|
||||||
|
inverterData(): Inverter[] {
|
||||||
|
return this.liveData.inverters;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -444,7 +447,7 @@ export default defineComponent({
|
|||||||
fetch("/api/livedata/status")
|
fetch("/api/livedata/status")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.inverterData = data;
|
this.liveData = data;
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -459,7 +462,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.socket.onmessage = (event) => {
|
this.socket.onmessage = (event) => {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
this.inverterData = JSON.parse(event.data);
|
this.liveData = JSON.parse(event.data);
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
this.heartCheck(); // Reset heartbeat detection
|
this.heartCheck(); // Reset heartbeat detection
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user