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..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 @@ -174,8 +174,7 @@ function processHierarchy(hierarchy: Hierarchy) { addBattery(hierarchy.id) break case 'inverter': - // addInverter (todo) - // console.info('inverter id ' + hierarchy.id) + addPvSystem(hierarchy.id) break default: // console.warn('Ignored Hierarchy type: ' + hierarchy.type) @@ -188,25 +187,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/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 cecbe1de83..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,25 +1,36 @@ - + 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..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 @@ -10,14 +10,15 @@ :corner-radius="cornerRadius" :circle-gap-size="circleGapSize" :empty-power="emptyPower" + :show-labels="globalConfig.showPmLabels" /> @@ -147,6 +148,18 @@ > Peak: {{ maxPowerString }} + + {{ '\uf05a' }} + @@ -166,7 +179,6 @@ import { usageSummary, masterData, } from '@/assets/js/model' -import { shDevices } from '../smartHome/model' import { chargePoints, vehicles, @@ -183,7 +195,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 +211,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 +280,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,