Hoecki
(Holger Höckmann)
December 23, 2021, 5:24pm
1
Based on inspirations here in the community. I created a widget for a PV solar plant with battery.
Changelog
Version 0.3
Introduced text: =items[props.item_grid].displayState || items[props.item_grid].state as suggested by DiegoDf (Thx!).
Version 0.2
removed default value for threshold to allow import via marketplace
Version 0.1
Resources
uid: solar_plant_state
tags:
- cell
- solar
props:
parameters:
- description: Name of the solar plant
label: Name
name: prop_name
required: false
type: TEXT
- context: item
description: Item holding the current grid power (+ = green; - = red)
label: Grid Power
name: item_grid
required: false
type: TEXT
- context: item
description: Item holding the current house power Consumption
label: House Power
name: item_house
required: false
type: TEXT
- context: item
description: Item holding the current solar power
label: Solar Power
name: item_solar
required: false
type: TEXT
- context: item
description: Item holding the current battery power (+ = green; - = red)
label: Battery Power
name: item_bat
required: false
type: TEXT
- context: item
description: Item holding the battery level
label: Battery Level
name: item_soc
required: false
type: TEXT
- description: Treshold for Pause
label: Treshold
name: prop_tres
required: true
type: INTEGER
parameterGroups:
- name: action1
context: action
label: Action, when items clicked
component: f7-card
config:
title: =props.prop_name
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
color: "=(themeOptions.dark === 'light') ? 'black' : 'white'"
style:
font-size: 16px
font-weight: bold
text: =items[props.item_grid].displayState || items[props.item_grid].state
- component: f7-row
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-icon
config:
f7: power
size: 40
- component: f7-col
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-icon
config:
color: "=(Number.parseInt(items[props.item_grid].state) > props.prop_tres) ? 'dark_red' : (Number.parseInt(items[props.item_grid].state) < -1 * props.prop_tres) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(items[props.item_grid].state) > props.prop_tres) ? 'arrow_right_circle' : (Number.parseInt(items[props.item_grid].state) < -1 * props.prop_tres) ? 'arrow_left_circle' : 'pause_circle'"
size: 40
- component: f7-col
config:
class:
- display-flex
- flex-direction-column
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
font-weight: bold
text: =items[props.item_house].displayState || items[props.item_house].state
- component: f7-icon
config:
class:
- align-self-center
f7: house_alt
size: 60
- component: f7-icon
config:
class:
- align-self-center
color: "=(Number.parseInt(items[props.item_bat].state) > props.prop_tres) ? 'dark_red' : (Number.parseInt(items[props.item_bat].state) < -1 * props.prop_tres) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(items[props.item_bat].state) > props.prop_tres) ? 'arrow_up_circle' : (Number.parseInt(items[props.item_bat].state) < -1 * props.prop_tres) ? 'arrow_down_circle' : 'pause_circle'"
size: 40
- component: oh-icon
config:
class:
- display-flex
- justify-content-center
icon: battery
state: =items[props.item_soc].state
style:
height: 60px
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
font-weight: bold
text: =items[props.item_bat].displayState || items[props.item_bat].state
- component: f7-col
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
font-weight: bold
text: =items[props.item_solar].displayState || items[props.item_solar].state
- component: f7-row
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-icon
config:
color: "=(Number.parseInt(items[props.item_solar].state) > props.prop_tres) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(items[props.item_solar].state) > props.prop_tres) ? 'arrow_left_circle' : 'pause_circle'"
size: 40
- component: f7-col
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: f7-icon
config:
f7: sun_max
size: 40
4 Likes
Hello,
Unfortunately the widget can no longer be installed under Openhab 3.3 M1. It always runs against an error.
hmerk
(Hans-Jörg Merk)
February 4, 2022, 4:23pm
3
Could you please show the errorâŠ
On the UI, this error comes after I click on ADD.
Installation of add-on 130502 failed
/var/log/openhab/openhab.log
2022-02-04 18:04:15.026 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Widget from marketplace is invalid: Unable to parse YAML
2022-02-04 18:04:36.160 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Unable to parse YAML: Unrecognized field âdefaultâ (class org.openhab.core.config.core.dto.ConfigDescriptionParameterDTO), not marked as ignorable (22 known properties: âreadOnlyâ, âmaxâ, âlimitToOptionsâ, âgroupNameâ, ânameâ, âstepsizeâ, âcontextâ, âdefaultValueâ, âminâ, âlabelâ, âfilterCriteriaâ, âverifyâ, âtypeâ, âdescriptionâ, âoptionsâ, ârequiredâ, âadvancedâ, âunitâ, âmultipleLimitâ, âpatternâ, âmultipleâ, âunitLabelâ])
at [Source: (StringReader); line: 40, column: 20] (through reference chain: org.openhab.core.ui.components.RootUIComponent[âpropsâ]->org.openhab.core.config.core.dto.ConfigDescriptionDTO[âparametersâ]->java.util.ArrayList[6]->org.openhab.core.config.core.dto.ConfigDescriptionParameterDTO[âdefaultâ])
hmerk
(Hans-Jörg Merk)
February 4, 2022, 5:09pm
5
There is the issue, happend to one of my widgets as well.
Needs to be renamed to âdefaultValueâ.
@Hoecki Could you please change your widget.
Hoecki
(Holger Höckmann)
February 4, 2022, 5:31pm
6
When I try to change it in my Openhab 3.2 Installation, it changes automatically back in the yaml-Editor to âdefaultâ.
It think its best not to change it here yet, b/c it may break the functionality for 3.2 - Users. Iâm not able to test with Milestone-Builds.
@Christian_Thiele I suggest to manually copy the yaml-code to your installation and change line 42 as suggested by hmerk until release of 3.3.
hmerk
(Hans-Jörg Merk)
February 4, 2022, 6:03pm
7
It is not connected to the Milestone build, changes in core happened early 2021âŠ
@ysc Is there an UI issue, as you said earlier it is a leftover.
ysc
(Yannick Schaus)
February 4, 2022, 8:20pm
8
itâs been changed from defaultValue to default in
openhab:main
â cweitkamp:feature-config-dto-default
opened 03:15PM - 25 May 21 UTC
- Changed `ConfigDescriptionParameterDTO` field serialization: "defaultValue" ->⊠"default"
- Fixed a minor bug in `ConfigDescriptionDTOMapper` for field "unit"
- Added unit tests for `ConfigDescriptionDTOMapper`, `ConfigDescriptionResource` and `AutomationIntegrationJsonTest`
Supersedes #2376
Related to #2148
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
however it applies only to (de)serialization to/from JSON, I just realized the YAML deserializer (also in core, to import the marketplace entry) might not be aware of that mapping.
Hoecki
(Holger Höckmann)
February 5, 2022, 8:48am
9
I removed the âcriticalâ parameter. Itâs not necessary, just comfort. Please try again.
1 Like
DiegoDf
(Diego)
February 6, 2022, 2:03pm
10
For me, the numeric values were not displayed. The reason was, that for my file based items there was no displayState. In this discussion it appears that there is not always a displayState available for each item.
The solution is simple. The line:
text: =items[props.item_grid].displayState
should be replaced by:
text: =items[props.item_grid].displayState || items[props.item_grid].state
The other lines with numeric values should be modified too.
You can test your items with the âWidgets Expression Testerâ:
2 Likes
The widget is working fine now. I.e. the Installtion went without problems and also the values are displayed. Only the arrows (red/green) are not displayed. Here are only pause characters to see.
Hoecki
(Holger Höckmann)
February 7, 2022, 7:32pm
12
You need to set a threshold value, e.g. 50.
Thanks for the answer. Works. I have one more request. I have from the MPPT two values for the battery. Once for charging (so solar to battery) and once discharging (from battery to house).
Could you include another item here? So charging power and discharging power?
Hoecki
(Holger Höckmann)
February 12, 2022, 11:39am
14
I suggest to use a proxy item, which is calculated from the two MPPT-items by a rule.
Result has to be negative for discharging and positive for charging.
I think itâs just the sum of the two with the correct prefix.
Thatâs the easiest solution. In the widget it would be some effort to handle prefix and the two different conditions (1 vs. 2 items).
Hi is there a way to add a second battery and an car? so that i have all the informations in this overview?
herrmi
(Markus Herrmannsdörfer)
January 5, 2024, 7:33am
16
Thanks for the widget. I like the simplicity a lot. I modified it to some degree for my setup.
Code:
uid: Solar_Plant_Widget
tags: []
props:
parameters:
- context: item
label: Netzleistung
name: grid_power
required: true
type: TEXT
- context: item
label: Gesamtverbrauch
name: load_power
required: true
type: TEXT
- context: item
label: PV Leistung
name: solar_power
required: true
type: TEXT
- context: item
label: Batterieleistung
name: battery_power
required: true
type: TEXT
- context: item
label: Batterie Ladezustand
name: battery_soc
required: true
type: TEXT
- description: Minimale Leistung
label: Minimale Leistung
name: min_power
required: true
type: INTEGER
- context: item
label: Autarkie
name: autonomy
required: true
type: TEXT
- context: item
label: Eigenverbrauch
name: self_consumption
required: true
type: TEXT
parameterGroups:
- name: action1
context: action
label: Action, when items clicked
timestamp: Jan 5, 2024, 6:38:14 AM
component: f7-card
config:
class:
- display-flex
- flex-direction-column
- align-items-center
style:
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
margin-left: 5px
margin-right: 5px
noShadow: false
padding: 0px
height: 210px
slots:
content:
- component: f7-block
config:
style:
align-items: center
justify-content: center
margin-top: -10px
width: 350px
slots:
default:
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: f7-col
- component: f7-col
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
f7: sun_max_fill
size: 60
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
class:
- display-flex
- justify-content-center
- align-self-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =@props.solar_power
- component: f7-col
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: f7-col
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
class:
- display-flex
- justify-content-center
- align-self-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =@props.autonomy
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
color: "=(Number.parseInt(@props.solar_power) > props.min_power) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(@props.solar_power) > props.min_power) ? 'arrow_down_circle' : 'pause_circle'"
size: 40
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
class:
- display-flex
- justify-content-center
- align-self-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =@props.self_consumption
- component: f7-col
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
f7: bolt_circle
size: 60
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
color: "=(Number.parseInt(@props.grid_power) > props.min_power) ? 'red' : (Number.parseInt(@props.grid_power) < -props.min_power) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(@props.grid_power) > props.min_power) ? 'arrow_right_circle' : (Number.parseInt(@props.grid_power) < -props.min_power) ? 'arrow_left_circle' : 'pause_circle'"
size: 40
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
f7: house
size: 60
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: f7-icon
config:
class:
- align-self-center
color: "=(Number.parseInt(@props.battery_power) > props.min_power) ? 'red' : (Number.parseInt(@props.battery_power) < -props.min_power) ? 'green' : (themeOptions.dark === 'light') ? 'black' : 'white'"
f7: "=(Number.parseInt(@props.battery_power) > props.min_power) ? 'arrow_left_circle' : (Number.parseInt(@props.battery_power) < -props.min_power) ? 'arrow_right_circle' : 'pause_circle'"
size: 40
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
- align-items-center
color: "=Number.parseFloat(@props.battery_soc) < 20 ? 'red' : (Number.parseFloat(@props.battery_soc) < 60 ? 'orange' : 'green')"
style:
font-size: 16px
text: =@props.battery_soc
- component: oh-icon
config:
class:
- display-flex
- justify-content-center
- align-items-center
icon: battery
state: =Number.parseFloat(@props.battery_soc)
style:
margin-top: -15px
height: 50px
- component: f7-row
config:
style:
align-items: center
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center - align-self-center
color: "=Number.parseFloat(@props.grid_power) < 0 ? 'green' : Number.parseFloat(@props.grid_power) > 0 ? 'red' : themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =Math.abs(Number.parseInt(@props.grid_power)) + ' W'
- component: f7-col
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
- align-self-center
color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =Math.abs(Number.parseInt(@props.load_power)) + ' W'
- component: f7-col
- component: f7-col
config:
class:
- display-flex
- justify-content-center
- flex-direction-column
slots:
default:
- component: oh-button
config:
actionPropsParameterGroup: action1
class:
- display-flex
- justify-content-center
- align-self-center
color: "=Number.parseFloat(@props.battery_power) < 0 ? 'green' : Number.parseFloat(@props.battery_power) > 0 ? 'red' : themeOptions.dark === 'light' ? 'black' : 'white'"
style:
font-size: 16px
text: =Math.abs(Number.parseInt(@props.battery_power)) + ' W'