diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index e30ec313b..6ee77bfdb 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -302,6 +302,15 @@ void WebApiWsLiveClass::generateInverterChannelJsonResponse(JsonObject& root, st addField(chanTypeObj, inv, t, c, FLD_PAC); addField(chanTypeObj, inv, t, c, FLD_UAC); addField(chanTypeObj, inv, t, c, FLD_IAC); + // Add HMT-specific 3-phase fields if available + if (t == TYPE_AC) { + addField(chanTypeObj, inv, t, c, FLD_UAC_1N); + addField(chanTypeObj, inv, t, c, FLD_UAC_2N); + addField(chanTypeObj, inv, t, c, FLD_UAC_3N); + addField(chanTypeObj, inv, t, c, FLD_IAC_1); + addField(chanTypeObj, inv, t, c, FLD_IAC_2); + addField(chanTypeObj, inv, t, c, FLD_IAC_3); + } if (t == TYPE_INV) { addField(chanTypeObj, inv, t, c, FLD_PDC, "Power DC"); } else { diff --git a/webapp/src/components/InverterChannelInfo.vue b/webapp/src/components/InverterChannelInfo.vue index b7ebc27ba..36d00342a 100644 --- a/webapp/src/components/InverterChannelInfo.vue +++ b/webapp/src/components/InverterChannelInfo.vue @@ -11,12 +11,17 @@
- +
- {{ $t('inverterchannelinfo.Phase', { num: channelNumber + 1 }) }} + +
@@ -48,9 +53,10 @@ import { defineComponent, type PropType } from 'vue'; export default defineComponent({ props: { - channelData: { type: Object as PropType, required: true }, + channelData: { type: Object as PropType>, required: true }, channelType: { type: String, required: true }, channelNumber: { type: Number, required: true }, + phaseNumber: { type: Number, required: false }, }, }); diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 44de8cc57..6b154c988 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -446,6 +446,7 @@ "inverterchannelinfo": { "String": "String {num}", "Phase": "Phase {num}", + "AC": "AC", "General": "General" }, "invertertotalinfo": { diff --git a/webapp/src/types/LiveDataStatus.ts b/webapp/src/types/LiveDataStatus.ts index 71da175a8..f702e05a2 100644 --- a/webapp/src/types/LiveDataStatus.ts +++ b/webapp/src/types/LiveDataStatus.ts @@ -19,6 +19,13 @@ export interface InverterStatistics { ReactivePower?: ValueObject; Efficiency?: ValueObject; Irradiation?: ValueObject; + // 3-phase fields for HMT inverters + 'Voltage Ph1-N'?: ValueObject; + 'Voltage Ph2-N'?: ValueObject; + 'Voltage Ph3-N'?: ValueObject; + 'Current Ph1'?: ValueObject; + 'Current Ph2'?: ValueObject; + 'Current Ph3'?: ValueObject; } export interface RadioStatistics { diff --git a/webapp/src/views/HomeView.vue b/webapp/src/views/HomeView.vue index 69545f06e..61dc9610a 100644 --- a/webapp/src/views/HomeView.vue +++ b/webapp/src/views/HomeView.vue @@ -190,22 +190,15 @@ ].reverse()" > @@ -528,7 +567,7 @@ import type { GridProfileRawdata } from '@/types/GridProfileRawdata'; import type { GridProfileStatus } from '@/types/GridProfileStatus'; import type { LimitConfig } from '@/types/LimitConfig'; import type { LimitStatus } from '@/types/LimitStatus'; -import type { Inverter, LiveData } from '@/types/LiveDataStatus'; +import type { Inverter, LiveData, InverterStatistics } from '@/types/LiveDataStatus'; import { authHeader, authUrl, handleResponse, isLoggedIn } from '@/utils/authentication'; import * as bootstrap from 'bootstrap'; import { @@ -992,6 +1031,50 @@ export default defineComponent({ } return this.$n(val_small / val_large, 'percent'); }, + isThreePhaseInverter(inverter: Inverter): boolean { + // Check if the inverter has 3-phase specific fields + if (!inverter.AC || !inverter.AC[0]) { + return false; + } + + const acData = inverter.AC[0]; + // Look for 3-phase specific field names + const hasPhase1Voltage = !!acData['Voltage Ph1-N']; + const hasPhase2Voltage = !!acData['Voltage Ph2-N']; + const hasPhase3Voltage = !!acData['Voltage Ph3-N']; + + return hasPhase1Voltage && hasPhase2Voltage && hasPhase3Voltage; + }, + getPhaseDataWithPower(acData: InverterStatistics, phase: number): Partial { + // Extract data for a specific phase from the AC data with calculated power + const phaseData: Partial = {}; + + // Copy phase-specific voltage field + const voltageField = `Voltage Ph${phase}-N` as keyof InverterStatistics; + if (acData[voltageField]) { + phaseData.Voltage = acData[voltageField]; + } + + // Copy phase-specific current field + const currentField = `Current Ph${phase}` as keyof InverterStatistics; + if (acData[currentField]) { + phaseData.Current = acData[currentField]; + } + + // Calculate power for this phase: P = V * I * PowerFactor + if (phaseData.Voltage && phaseData.Current) { + const powerFactor = acData.PowerFactor?.v ?? 1; // Default to 1 if not available + + phaseData.Power = { + v: phaseData.Voltage.v * phaseData.Current.v * powerFactor, + u: 'W', + d: 2, + max: 0, + }; + } + + return phaseData; + }, }, });