From cea5101da59f16e6acf2cd1ae2c288be05c776c1 Mon Sep 17 00:00:00 2001 From: Claus Hagen Date: Sat, 2 Aug 2025 08:15:11 +0200 Subject: [PATCH 1/5] add details information to powermeter --- .../colors/source/src/assets/css/style.css | 2 +- .../colors/source/src/assets/js/helpers.ts | 12 ++ .../colors/source/src/assets/js/model.ts | 78 ++++++-- .../source/src/assets/js/processMessages.ts | 41 ++-- .../source/src/assets/js/themeConfig.ts | 16 ++ .../colors/source/src/assets/js/types.ts | 24 ++- .../components/batteryList/BatteryList.vue | 14 +- .../src/components/batteryList/model.ts | 10 +- .../chargePointList/CPChargePoint.vue | 20 +- .../src/components/chargePointList/model.ts | 9 +- .../src/components/counterList/model.ts | 14 +- .../components/energyMeter2/EnergyMeter2.vue | 4 +- .../components/inverterList/InverterList.vue | 13 +- .../src/components/powerMeter/PMSourceArc.vue | 134 +++++++++++-- .../src/components/powerMeter/PMUsageArc.vue | 177 ++++++++++++++++-- .../src/components/powerMeter/PowerMeter.vue | 22 ++- .../source/src/components/smartHome/model.ts | 2 + .../components/smartHome/processMessages.ts | 2 + 18 files changed, 495 insertions(+), 99 deletions(-) diff --git a/packages/modules/web_themes/colors/source/src/assets/css/style.css b/packages/modules/web_themes/colors/source/src/assets/css/style.css index d98dbda359..b4c10e0b1b 100644 --- a/packages/modules/web_themes/colors/source/src/assets/css/style.css +++ b/packages/modules/web_themes/colors/source/src/assets/css/style.css @@ -178,7 +178,7 @@ body>.container-fluid { --color-house: #7f7f7f; --color-charging: #1f78b4; --color-export: #b2df8a; - --color-battery: goldenrod; + --color-battery: #daa520; --color-input: lightgrey; --color-pv1: #33a02c; --color-pv2: #4db662; diff --git a/packages/modules/web_themes/colors/source/src/assets/js/helpers.ts b/packages/modules/web_themes/colors/source/src/assets/js/helpers.ts index 43c9c965ac..e9009121aa 100755 --- a/packages/modules/web_themes/colors/source/src/assets/js/helpers.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/helpers.ts @@ -121,3 +121,15 @@ export function formatTemp(t: number) { }) + '°' : '-' } + +export function fgColor(colorname: string) { + const root = document.documentElement + const style = getComputedStyle(root) + colorname = colorname.slice(4, -1) // remove 'var(...)' + const bgColor = style.getPropertyValue(colorname).trim() + const r = parseInt(bgColor.slice(1, 3), 16) + const g = parseInt(bgColor.slice(3, 5), 16) + const b = parseInt(bgColor.slice(5, 7), 16) + const brightness = (r * 299 + g * 587 + b * 114) / 1000 + return brightness > 125 ? 'black' : 'white' +} diff --git a/packages/modules/web_themes/colors/source/src/assets/js/model.ts b/packages/modules/web_themes/colors/source/src/assets/js/model.ts index ea269112ef..ad24452163 100644 --- a/packages/modules/web_themes/colors/source/src/assets/js/model.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/model.ts @@ -9,7 +9,7 @@ import { reactive, ref } from 'vue' import { GlobalData } from './themeConfig' -import type { PowerItem, ItemProps } from './types' +import { type PowerItem, type ItemProps, PowerItemType } from './types' import { PvSystem } from './types' export const masterData: { [key: string]: ItemProps } = reactive({ @@ -86,10 +86,43 @@ class HistoricSummary { values() { return Object.values(this._items) } - addItem(key: string, useColor?: string) { + addItem(key: string, type?: PowerItemType, useColor?: string) { + let itemType: PowerItemType + if (type) { + itemType = type + } else { + switch (key) { + case 'evuIn': + itemType = PowerItemType.counter + break + case 'pv': + itemType = PowerItemType.inverter + break + case 'batOut': + itemType = PowerItemType.battery + break + case 'evuOut': + itemType = PowerItemType.counter + break + case 'charging': + itemType = PowerItemType.chargepoint + break + case 'devices': + itemType = PowerItemType.device + break + case 'batIn': + itemType = PowerItemType.battery + break + case 'house': + itemType = PowerItemType.house + break + default: + itemType = PowerItemType.counter + } + } this._items[key] = useColor - ? createPowerItem(key, useColor) - : createPowerItem(key) + ? createPowerItem(key, itemType, useColor) + : createPowerItem(key, itemType) } setEnergy(cat: string, val: number) { if (!this.keys().includes(cat)) { @@ -131,23 +164,28 @@ export function resetHistoricSummary() { historicSummary = new HistoricSummary() } export const sourceSummary: { [key: string]: PowerItem } = reactive({ - evuIn: createPowerItem('evuIn'), - pv: createPowerItem('pv'), - batOut: createPowerItem('batOut'), + evuIn: createPowerItem('evuIn', PowerItemType.counter), + pv: createPowerItem('pv', PowerItemType.pvSummary), + batOut: createPowerItem('batOut', PowerItemType.batterySummary), }) export const usageSummary: { [key: string]: PowerItem } = reactive({ - evuOut: createPowerItem('evuOut'), - charging: createPowerItem('charging'), - devices: createPowerItem('devices'), - batIn: createPowerItem('batIn'), - house: createPowerItem('house'), + evuOut: createPowerItem('evuOut', PowerItemType.counter), + charging: createPowerItem('charging', PowerItemType.chargeSummary), + devices: createPowerItem('devices', PowerItemType.deviceSummary), + batIn: createPowerItem('batIn', PowerItemType.batterySummary), + house: createPowerItem('house', PowerItemType.house), }) export const globalData = reactive(new GlobalData()) export const etPriceList = ref('') export const energyMeterNeedsRedraw = ref(false) -function createPowerItem(key: string, useColor?: string): PowerItem { +function createPowerItem( + key: string, + type: PowerItemType, + useColor?: string, +): PowerItem { const p: PowerItem = { name: masterData[key] ? masterData[key].name : 'item', + type: type, power: 0, energy: 0, energyPv: 0, @@ -172,6 +210,16 @@ export const currentTime = ref(new Date()) export const pvSystems = ref(new Map()) export const addPvSystem = (index: number) => { pvSystems.value.set(index, new PvSystem(index)) - pvSystems.value.get(index)!.color = - masterData['pv' + pvSystems.value.size].color + assignPvSystemColors() + //pvSystems.value.get(index)!.color = + //masterData['pv' + pvSystems.value.size].color +} + +function assignPvSystemColors() { + const pvSystemsSorted = [...pvSystems.value.values()].sort( + (a, b) => a.id - b.id, + ) + pvSystemsSorted.forEach((system, index) => { + system.color = masterData['pv' + (index + 1)].color + }) } diff --git a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts index 2e8c7f9421..41a78e8f7b 100755 --- a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts @@ -174,8 +174,8 @@ function processHierarchy(hierarchy: Hierarchy) { addBattery(hierarchy.id) break case 'inverter': - // addInverter (todo) - // console.info('inverter id ' + hierarchy.id) + addPvSystem(hierarchy.id) + console.info('new inverter id ' + hierarchy.id) break default: // console.warn('Ignored Hierarchy type: ' + hierarchy.type) @@ -188,25 +188,26 @@ function processHierarchy(hierarchy: Hierarchy) { function processPvMessages(topic: string, message: string) { const index = getIndex(topic) if (index && !pvSystems.value.has(index)) { - // console.warn('Creating PV system: ' + index) - addPvSystem(index) - } - if (topic == 'openWB/pv/get/power') { - sourceSummary.pv.power = -message - } else if (topic == 'openWB/pv/get/daily_exported') { - sourceSummary.pv.energy = +message - } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/power$/i)) { - pvSystems.value.get(index!)!.power = +message - } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/daily_exported$/i)) { - pvSystems.value.get(index!)!.energy = +message - } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/monthly_exported$/i)) { - pvSystems.value.get(index!)!.energy_month = +message - } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/yearly_exported$/i)) { - pvSystems.value.get(index!)!.energy_year = +message - } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/exported$/i)) { - pvSystems.value.get(index!)!.energy_total = +message + console.warn('Invalid PV system index: ' + index) + // addPvSystem(index) } else { - // console.warn('Ignored PV msg: [' + topic + '] ' + message) + if (topic == 'openWB/pv/get/power') { + sourceSummary.pv.power = -message + } else if (topic == 'openWB/pv/get/daily_exported') { + sourceSummary.pv.energy = +message + } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/power$/i)) { + pvSystems.value.get(index!)!.power = +message + } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/daily_exported$/i)) { + pvSystems.value.get(index!)!.energy = +message + } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/monthly_exported$/i)) { + pvSystems.value.get(index!)!.energy_month = +message + } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/yearly_exported$/i)) { + pvSystems.value.get(index!)!.energy_year = +message + } else if (topic.match(/^openWB\/pv\/[0-9]+\/get\/exported$/i)) { + pvSystems.value.get(index!)!.energy_total = +message + } else { + // console.warn('Ignored PV msg: [' + topic + '] ' + message) + } } } diff --git a/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts b/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts index 15fb212c61..e215dd9572 100644 --- a/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/themeConfig.ts @@ -42,6 +42,7 @@ export class Config { private _debug: boolean = false private _lowerPriceBound = 0 private _upperPriceBound = 0 + private _showPmLabels = true isEtEnabled: boolean = false etPrice: number = 20.5 showRightButton = true @@ -318,6 +319,16 @@ export class Config { setUpperPriceBound(val: number) { this._upperPriceBound = val } + get showPmLabels() { + return this._showPmLabels + } + set showPmLabels(val: boolean) { + this._showPmLabels = val + savePrefs() + } + setShowPmLabels(val: boolean) { + this._showPmLabels = val + } } export const globalConfig = reactive(new Config()) @@ -494,6 +505,7 @@ interface Preferences { lowerP?: number upperP?: number sslPrefs?: boolean + pmLabels?: boolean debug?: boolean } @@ -527,6 +539,7 @@ function writeCookie() { prefs.lowerP = globalConfig.lowerPriceBound prefs.upperP = globalConfig.upperPriceBound prefs.sslPrefs = globalConfig.sslPrefs + prefs.pmLabels = globalConfig.showPmLabels prefs.debug = globalConfig.debug document.cookie = @@ -626,6 +639,9 @@ function readCookie() { if (prefs.sslPrefs !== undefined) { globalConfig.setSslPrefs(prefs.sslPrefs) } + if (prefs.pmLabels !== undefined) { + globalConfig.setShowPmLabels(prefs.pmLabels) + } if (prefs.debug !== undefined) { globalConfig.setDebug(prefs.debug) } diff --git a/packages/modules/web_themes/colors/source/src/assets/js/types.ts b/packages/modules/web_themes/colors/source/src/assets/js/types.ts index 00164a9e16..2aed6c380a 100644 --- a/packages/modules/web_themes/colors/source/src/assets/js/types.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/types.ts @@ -9,6 +9,7 @@ export class ShDevice implements PowerItem { id: number name = '' + type = PowerItemType.device power = 0 energy = 0 energyPv = 0 @@ -49,9 +50,21 @@ export interface ItemProps { color: string icon: string } - +export enum PowerItemType { + counter = 'counter', + inverter = 'inverter', + pvSummary = 'pvSummary', + battery = 'battery', + batterySummary = 'batterySummary', + chargepoint = 'chargepoint', + chargeSummary = 'chargeSummary', + device = 'device', + deviceSummary = 'deviceSummary', + house = 'house', +} export interface PowerItem { name: string + type: PowerItemType power: number energy: number energyPv: number @@ -73,16 +86,21 @@ export interface MarginType { bottom: number } -export class PvSystem { +export class PvSystem implements PowerItem { id: number name = 'Wechselrichter' + type = PowerItemType.inverter color = 'var(--color-pv)' power = 0 energy = 0 energy_month = 0 energy_year = 0 energy_total = 0 - + energyPv = 0 + energyBat = 0 + pvPercentage = 0 + icon = '' + showInGraph = true constructor(index: number) { this.id = index } diff --git a/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue b/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue index 60dccbb4ac..d070ae4528 100755 --- a/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue +++ b/packages/modules/web_themes/colors/source/src/components/batteryList/BatteryList.vue @@ -36,12 +36,14 @@ Hagen */ - +
+ +
diff --git a/packages/modules/web_themes/colors/source/src/components/batteryList/model.ts b/packages/modules/web_themes/colors/source/src/components/batteryList/model.ts index f6aa31cadb..a876c5bab0 100755 --- a/packages/modules/web_themes/colors/source/src/components/batteryList/model.ts +++ b/packages/modules/web_themes/colors/source/src/components/batteryList/model.ts @@ -5,10 +5,12 @@ */ import { masterData } from '@/assets/js/model' +import { PowerItemType, type PowerItem } from '@/assets/js/types' import { reactive, ref } from 'vue' -export class Battery { +export class Battery implements PowerItem { id: number name = 'Speicher' + type = PowerItemType.battery color = 'var(--color-battery)' dailyYieldExport = 0 dailyYieldImport = 0 @@ -22,6 +24,12 @@ export class Battery { imported = 0 power = 0 soc = 0 + energy = 0 + energyPv = 0 + energyBat = 0 + pvPercentage = 0 + showInGraph = true + icon = 'Speicher' constructor(index: number) { this.id = index } diff --git a/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue b/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue index 5aca627f72..4ae1bc2696 100644 --- a/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue +++ b/packages/modules/web_themes/colors/source/src/components/chargePointList/CPChargePoint.vue @@ -22,7 +22,6 @@ @@ -71,11 +70,7 @@ @@ -97,7 +92,6 @@ diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue index f1ddb70d3f..a3bc319f22 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue @@ -10,6 +10,7 @@ :corner-radius="cornerRadius" :circle-gap-size="circleGapSize" :empty-power="emptyPower" + :show-labels="globalConfig.showPmLabels" /> @@ -147,6 +149,18 @@ > Peak: {{ maxPowerString }} + + {{ '\uf05a' }} + @@ -183,7 +197,7 @@ import { etData } from '../priceChart/model' const width = 500 const height = width const margin = 20 -const cornerRadius = 1 +const cornerRadius = 20 const circleGapSize = Math.PI / 40 const schemes = [[4], [4, 6], [1, 4, 6], [0, 2, 4, 6], [0, 2, 3, 5, 6]] @@ -199,7 +213,7 @@ const labelPositions = [ { x: 0, y: ((height / 2) * 3) / 5 }, ] const radius = computed(() => { - return width / 2 - margin + return width / 2.0 - margin }) const currentConsumptionString = computed(() => { let consumptionLabel = '' @@ -268,6 +282,10 @@ const currentPrice = computed(() => { const [p] = etData.etPriceList.values() return Math.round(p * 10) / 10 }) +function toggleInfo() { + //showLabels.value = !showLabels.value + globalConfig.showPmLabels = !globalConfig.showPmLabels +} diff --git a/packages/modules/web_themes/colors/source/src/components/smartHome/model.ts b/packages/modules/web_themes/colors/source/src/components/smartHome/model.ts index ccb25d264f..d1f39cc517 100755 --- a/packages/modules/web_themes/colors/source/src/components/smartHome/model.ts +++ b/packages/modules/web_themes/colors/source/src/components/smartHome/model.ts @@ -1,9 +1,11 @@ import { reactive } from 'vue' import { savePrefs } from '@/assets/js/themeConfig' import { historicSummary } from '@/assets/js/model' +import { PowerItemType } from '@/assets/js/types' export class ShDevice { id: number name = 'Gerät' + type = PowerItemType.device power = 0 status = 'off' energy = 0 diff --git a/packages/modules/web_themes/colors/source/src/components/smartHome/processMessages.ts b/packages/modules/web_themes/colors/source/src/components/smartHome/processMessages.ts index f093fef30c..5d6957aa98 100755 --- a/packages/modules/web_themes/colors/source/src/components/smartHome/processMessages.ts +++ b/packages/modules/web_themes/colors/source/src/components/smartHome/processMessages.ts @@ -28,6 +28,8 @@ function processSmarthomeConfigMessages(topic: string, message: string) { ) ) { dev.configured = message != '0' + updateShSummary('power') + updateShSummary('energy') } else if ( topic.match( /^openWB\/LegacySmarthome\/config\/get\/Devices\/[0-9]+\/device_name$/i, From c81292af837774b756fdb23784b47928d24fe9d3 Mon Sep 17 00:00:00 2001 From: Claus Hagen Date: Sat, 2 Aug 2025 09:09:04 +0200 Subject: [PATCH 2/5] fix PV color in powergraph --- .../colors/source/src/assets/js/processMessages.ts | 1 - .../source/src/components/powerGraph/PgSourceGraph.vue | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts index 41a78e8f7b..8ffd67d740 100755 --- a/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts +++ b/packages/modules/web_themes/colors/source/src/assets/js/processMessages.ts @@ -175,7 +175,6 @@ function processHierarchy(hierarchy: Hierarchy) { break case 'inverter': addPvSystem(hierarchy.id) - console.info('new inverter id ' + hierarchy.id) break default: // console.warn('Ignored Hierarchy type: ' + hierarchy.type) diff --git a/packages/modules/web_themes/colors/source/src/components/powerGraph/PgSourceGraph.vue b/packages/modules/web_themes/colors/source/src/components/powerGraph/PgSourceGraph.vue index a64be7c66d..ad06c1a01b 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerGraph/PgSourceGraph.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerGraph/PgSourceGraph.vue @@ -30,6 +30,7 @@ import { zoomedRange, type GraphDataItem, } from './model' +import { pvSystems } from '@/assets/js/model' const props = defineProps<{ width: number @@ -123,8 +124,9 @@ const keysToUse = computed(() => { } case 'today': case 'day': - additionalKeys.forEach((key, i) => { - colors[key] = 'var(--color-pv' + (i + 1) + ')' + additionalKeys.forEach((key) => { + colors[key] = + pvSystems.value.get(+key.slice(2))?.color ?? 'var(--color-pv)' }) return globalConfig.showInverters ? [...additionalKeys, ...k] From 584b915ebed4ae7e704789f429e88af12d76c00b Mon Sep 17 00:00:00 2001 From: Claus Hagen Date: Sat, 2 Aug 2025 17:36:38 +0200 Subject: [PATCH 3/5] clean up --- .../src/components/powerMeter/PMSourceArc.vue | 74 ++++++------ .../src/components/powerMeter/PMUsageArc.vue | 107 ++++++++---------- 2 files changed, 86 insertions(+), 95 deletions(-) diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue index 1e30b5206e..577fc12c98 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue @@ -46,40 +46,6 @@ const props = defineProps<{ // computed: const draw = computed(() => { // Draw the arc using d3 - let emptyPowerItem: PowerItem = { - name: '', - type: PowerItemType.counter, - power: props.emptyPower, - energy: 0, - energyPv: 0, - energyBat: 0, - pvPercentage: 0, - color: 'var(--color-bg)', - icon: '', - showInGraph: true, - } - let plotdata = [sourceSummary.evuIn] - if (pvSystems.value.size > 1) { - plotdata = plotdata.concat( - [...pvSystems.value.values()].sort((a, b) => { - return a.power - b.power - }) as PowerItem[], - ) - } else { - plotdata.push(sourceSummary.pv) - } - if (batteries.value.size > 1) { - plotdata = plotdata.concat( - [...batteries.value.values()] - .filter((b) => b.power < 0) - .sort((a, b) => { - return a.power - b.power - }) as PowerItem[], - ) - } else { - plotdata.push(sourceSummary.batOut) - } - plotdata = plotdata.concat(emptyPowerItem) const arcCount = Object.values(sourceSummary).length - 1 const pieGenerator = pie() .value((record: PowerItem) => Math.abs(record.power)) @@ -96,7 +62,7 @@ const draw = computed(() => { graph.selectAll('*').remove() const sources = graph .selectAll('sources') - .data(pieGenerator(Object.values(plotdata).filter((v) => v.power != 0))) + .data(pieGenerator(plotdata.value.filter((v) => v.power != 0))) .enter() sources @@ -113,6 +79,44 @@ const draw = computed(() => { addLabels(path, sources) return 'pmSourceArc.vue' }) +const plotdata = computed(() => { + return [sourceSummary.evuIn].concat( + invertersToShow.value, + batteriesToShow.value, + emptyPowerItem.value, + ) +}) +const invertersToShow = computed(() => + pvSystems.value.size > 1 + ? [...pvSystems.value.values()].sort((a, b) => { + return a.power - b.power + }) + : [sourceSummary.pv], +) +const batteriesToShow = computed(() => + batteries.value.size > 1 + ? [...batteries.value.values()] + .filter((b) => b.power < 0) + .sort((a, b) => { + return a.power - b.power + }) + : [sourceSummary.batOut], +) +const emptyPowerItem = computed(() => { + return { + name: '', + type: PowerItemType.counter, + power: props.emptyPower, + energy: 0, + energyPv: 0, + energyBat: 0, + pvPercentage: 0, + color: 'var(--color-bg)', + icon: '', + showInGraph: true, + } +}) + function addLabels( path: Arc>, consumers: Selection, BaseType, unknown>, diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMUsageArc.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMUsageArc.vue index 8ddcd0e53e..bb363da844 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMUsageArc.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMUsageArc.vue @@ -46,58 +46,7 @@ const props = defineProps<{ // computed: { const draw = computed(() => { // Draw the arc using d3 - let emptyPowerItem: PowerItem = { - name: '', - type: PowerItemType.counter, - power: props.emptyPower, - energy: 0, - energyPv: 0, - energyBat: 0, - pvPercentage: 0, - color: 'var(--color-bg)', - icon: '', - showInGraph: true, - } - // const plotdata = [usageSummary.evuOut, usageSummary.charging] - let plotdata = [usageSummary.evuOut] - if (Object.values(chargePoints).length > 1) { - plotdata = plotdata.concat( - Object.values(chargePoints).sort((a, b) => { - return b.power - a.power - }) as PowerItem[], - ) - } else { - plotdata = plotdata.concat([usageSummary.charging] as PowerItem[]) - } - - plotdata = plotdata.concat(plotdevices.value) - /* if (shDevices.size > 1) { - plotdata = plotdata - .concat( - [...shDevices.values()] - .filter((row) => row.configured && !row.countAsHouse && row.showInGraph) - .sort((a, b) => { - return b.power - a.power - }) as PowerItem[], - ) - } else { - plotdata.push(usageSummary.devices) - } */ - - if (Object.values(batteries).length > 1) { - plotdata = plotdata.concat( - [...batteries.value.values()] - .filter((b) => b.power > 0) - .sort((a, b) => { - return b.power - a.power - }) as PowerItem[], - ) - } else { - plotdata.push(usageSummary.batIn) - } - plotdata = plotdata.concat([usageSummary.house]).concat(emptyPowerItem) - - const arcCount = plotdata.length - 1 + const arcCount = plotdata.value.length - 1 const pieGenerator = pie() .value((record: PowerItem) => record.power) .startAngle(Math.PI * 1.5 - props.circleGapSize) @@ -112,7 +61,7 @@ const draw = computed(() => { graph.selectAll('*').remove() const consumers = graph .selectAll('consumers') - .data(pieGenerator(plotdata.filter((v) => v.power != 0))) + .data(pieGenerator(plotdata.value.filter((v) => v.power != 0))) .enter() consumers .append('path') @@ -133,8 +82,37 @@ const draw = computed(() => { return 'pmUsageArc.vue' }) - -const plotdevices = computed(() => { +const emptyPowerItem = computed(() => { + return { + name: '', + type: PowerItemType.counter, + power: props.emptyPower, + energy: 0, + energyPv: 0, + energyBat: 0, + pvPercentage: 0, + color: 'var(--color-bg)', + icon: '', + showInGraph: true, + } +}) +const plotdata = computed(() => { + return [usageSummary.evuOut].concat( + chargePointsToShow.value, + devicesToShow.value, + batteriesToShow.value, + usageSummary.house, + emptyPowerItem.value, + ) +}) +const chargePointsToShow = computed(() => { + return Object.values(chargePoints).length > 1 + ? Object.values(chargePoints).sort((a, b) => { + return b.power - a.power + }) + : [usageSummary.charging] +}) +const devicesToShow = computed(() => { let summarizedPower = 0 for (const d of shDevices.values()) { if (d.configured && !d.countAsHouse && !d.showInGraph) { @@ -153,18 +131,27 @@ const plotdevices = computed(() => { icon: '', showInGraph: true, } - return shDevices.size > 1 + let activeDevices = [...shDevices.values()].filter((row) => row.configured) + return activeDevices.length > 1 ? [deviceSummary].concat( - [...shDevices.values()] - .filter( - (row) => row.configured && !row.countAsHouse && row.showInGraph, - ) + activeDevices + .filter((row) => !row.countAsHouse && row.showInGraph) .sort((a, b) => { return b.power - a.power }), ) : [usageSummary.devices] }) +const batteriesToShow = computed(() => { + return batteries.value.size > 1 + ? [...batteries.value.values()] + .filter((b) => b.power > 0) + .sort((a, b) => { + return b.power - a.power + }) + : [usageSummary.batIn] +}) + function addLabels( path: Arc>, consumers: Selection, BaseType, unknown>, From ff5efa2848b3d24772da7bf8e6a182a996c9f171 Mon Sep 17 00:00:00 2001 From: Claus Hagen Date: Sun, 3 Aug 2025 15:24:04 +0200 Subject: [PATCH 4/5] refactor powergraph code --- .../src/components/powerMeter/PMArc.vue | 87 ++++++++++ .../src/components/powerMeter/PMPopup.vue | 63 +++++++ .../src/components/powerMeter/PMSourceArc.vue | 159 +++--------------- .../src/components/powerMeter/PMUsageArc.vue | 138 ++------------- .../src/components/powerMeter/PowerMeter.vue | 2 - 5 files changed, 187 insertions(+), 262 deletions(-) create mode 100644 packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue create mode 100644 packages/modules/web_themes/colors/source/src/components/powerMeter/PMPopup.vue diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue new file mode 100644 index 0000000000..1dd9a70cd4 --- /dev/null +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue @@ -0,0 +1,87 @@ + + + diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMPopup.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMPopup.vue new file mode 100644 index 0000000000..03f40918af --- /dev/null +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMPopup.vue @@ -0,0 +1,63 @@ + + + + diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue index 577fc12c98..354fc41150 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMSourceArc.vue @@ -1,38 +1,20 @@ - + diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue index a3bc319f22..3d67f74e36 100755 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PowerMeter.vue @@ -14,7 +14,6 @@ /> Date: Mon, 4 Aug 2025 08:36:48 +0200 Subject: [PATCH 5/5] hide popups for small power values --- .../colors/source/src/components/powerMeter/PMArc.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue index 1dd9a70cd4..fab8905e44 100644 --- a/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue +++ b/packages/modules/web_themes/colors/source/src/components/powerMeter/PMArc.vue @@ -33,7 +33,7 @@ :transform="'translate(' + path.centroid(consumer) + ')'" > @@ -83,5 +83,8 @@ function strokeColor(d: PieArcDatum, i: number): string { : 'null' : d.data.color } +const summarizedPower = computed (() => { + return props.plotdata.reduce((sum, item) => sum + item.power, 0) +})