Seite 1 von 2

2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 7. Jun 2025 16:20
von mad-mike
Moin zusammen.

Ich möchte ein Dashboard für die Anzeige der Solaranlage zur Visualisierung nutzen.
für die Anzeige ist es elementar, das ich die Leistungs nutzung vom Akku als 1 Item habe welches Positiv, wie auch Negative Zahlen anzeigt.

Pos Wert = Akku Entladen
Neg Wert = Akku Laden

Die beiden Item liegen mir als Text file und kommen über Modbus rein.

Ich würde ein Item erstellen wollen, welcher dann akku_power heisst, oder so. und dieses soll gefüttert werden.

Geht das nur über eine Rule??

:?: :?:

Und wie bekomme ich den Wert negativ angezeigt??

Danke und Gruss...

Code: Alles auswählen

Number Akku_watt "Akku Watt [%.1f W]" <flow> (gGrowatt) {channel="modbus:data:tcpBridge:inputPoller:Akku_watt:number"}
Number Akku_laden "Akku_laden [%.1f W]" <energy> (gGrowatt) {channel="modbus:data:tcpBridge:inputPoller:Akku_load:number"}

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 7. Jun 2025 20:26
von PeterA
Hi mad-mike,

endlich geht das Forum wieder wie toll!

Einen ähnlichen Usecase habe ich hier auch.
Von meinem Victron kommt das auch so ähnlich.
Akku wird geladen Wert positiv also >=0 und wenn entladen wird dann <=0 und mit negativem Vorzeichen.
Aber alles in einem Item.
Aber das ist letztendlich egal denn man kann ja in der UI mit
"visibility" und "labelcolor" usw Arbeiten.
Leider kann ich aktuell kein Code aus meiner Sitemap Posten
da ich unterwegs bin.
Aber im Prinzip kannst Du da genau definieren wann das Positive Item zu sehen und wann nicht usw.

Funktioniert sehr gut.

Gruß Peter

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 7. Jun 2025 22:27
von mad-mike
Aber alles in einem Item
Das brauche ich ja... ;)

Leider ist es bei mir getrennt. 2 Item, 2 positive zahlen.

Kann aber bei der grafischen anzeige nur 1 Item für die Akku Leistung einstellen.

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 7. Jun 2025 23:01
von peter-pan
mad-mike hat geschrieben: 7. Jun 2025 16:20 Ich möchte ein Dashboard für die Anzeige der Solaranlage zur Visualisierung nutzen
Was ist denn das für ein Dashboard ? Und wie bringst du die OH-Werte da hinein ?

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 8. Jun 2025 06:49
von Harka
Moin,
Du kannst den einen Wert mittels Profil auch in eine negative Zahl umwandeln. Ich nutze nicht die Textkonfiguration aber [profile="system:hysteresis", inverted="true"] wäre mein erster Versuch. Anschließend akku_power als nummerisches Gruppen-Item anlegen, welches die Summe von seinen beiden Mitgliedern bildet.

Im Prinzip geht auch was über Transformation, aber da habe ich jetzt keine 100% saubere Lösung hinbekommen und eine Rule ist imho der deutlich einfachere Weg.

E: an Stelle des Profils kann auch eine einzeilige Transformation (Multiplikation mit -1) in Frage kommen

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 8. Jun 2025 19:49
von mad-mike
Ich habe etwas probiert, und gemacht und getan...

Also, es handelt sich um das SMA Widget wo man die Akku Leistung als item eingeben muss.

ich hab mal versucht das ganze Widget um ein Item zu erweitern.. Nun habe ich hier 2 Item, und versuche diese ganzen regel zu verstehen,

Code: Alles auswählen

uid: SMA_widget
tags: []
props:
  parameters:
    - context: item
      label: Netzeinspeisung
      name: netzeinspeisung
      required: true
      type: TEXT
    - context: item
      label: Netzbezug
      name: netzbezug
      required: true
      type: TEXT
    - context: item
      label: Gesamtverbrauch
      name: gesamtverbrauch
      required: true
      type: TEXT
    - context: item
      label: PV Leistung
      name: pv_leistung
      required: true
      type: TEXT
    - context: item
      label: Batterieleistung_pos
      name: batterieleistung_pos
      required: true
      type: TEXT
    - context: item
      label: Batterieleistung_neg
      name: batterieleistung_neg
      required: true
      type: TEXT
    - context: item
      label: Batterie Ladezustand
      name: batterylevel
      required: true
      type: TEXT
  parameterGroups: []
timestamp: May 19, 2023, 2:50:20 PM
component: f7-card
config:
  class:
    - display-flex
    - flex-direction-column
    - align-items-center
  style:
    height: 383px
slots:
  content:
    - component: f7-block
      config:
        style:
          --f7-theme-color: var(--f7-text-color)
          display: flex
          justify-content: space-between
          padding: 0
      slots:
        default:
          - component: f7-col
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
            slots:
              default:
                - component: f7-block
                  config:
                    style:
                      align-items: center
                      display: flex
                      flex-direction: column
                      height: 110px
                      justify-content: center
                      margin-top: 0
                      width: 110px
                  slots:
                    default:
                      - component: oh-icon
                        config:
                          height: 110px
                          icon: sma_grid_2
                      - component: Label
                        config:
                          style:
                            color: red
                            font-size: 25px
                            font-weight: bold
                            margin-top: -10px
                            text-align: center
                            width: 100px
                          text: =items[props.netzbezug].displayState
                          visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0])
                            == 0) ? true : false'
                      - component: Label
                        config:
                          style:
                            color: green
                            font-size: 25px
                            font-weight: bold
                            margin-top: -10px
                            text-align: center
                            width: 100px
                          text: =items[props.netzeinspeisung].displayState
                          visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0])
                            > 0) ? true : false'
          - component: f7-col
            config:
              style:
                align-items: center
                display: flex
                flex-direction: column
                flex-grow: 1
            slots:
              default:
                - component: f7-block
                  config:
                    style:
                      align-items: center
                      display: flex
                      flex-direction: column
                      height: 110px
                      justify-content: center
                      margin-top: 0
                      width: 110px
                  slots:
                    default:
                      - component: Label
                        config:
                          style:
                            font-size: 25px
                            font-weight: bold
                            text-align: center
                            width: 100px
                          text: =items[props.pv_leistung].displayState
                      - component: oh-icon
                        config:
                          height: 110px
                          icon: sma_pv_2
                          style:
                            margin-top: -20px
                - component: f7-block
                  config:
                    style:
                      display: flex
                      justify-content: center
                      margin: 0
                      padding: 0
                      width: 100%
                  slots:
                    default:
                      - component: f7-row
                        config:
                          preserveAspectRatio: xMidYMid slice
                          style:
                            height: auto
                            width: auto
                          tag: svg
                          viewBox: 0 0 100 100
                          xmlns: http://www.w3.org/2000/svg
                        slots:
                          default:
                            - component: f7-row
                              config:
                                d: M60 -5 v10 c0 30 10 35 30 35 h20
                                fill: none
                                id: path1
                                stroke: rgba(100, 150, 200, 0.8)
                                stroke-width: 2
                                tag: path
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.batterieleistung_pos].state.split(" ")[0])
                                  > 0) ? true : false'
                            - component: f7-row
                              config:
                                fill: rgba(100, 150, 200, 0.8)
                                r: 6
                                style:
                                  stroke-width: 4
                                tag: circle
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.batterieleistung_pos].state.split(" ")[0])
                                  > 0) ? true : false'
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      calcMode: linear
                                      dur: 4s
                                      repeatCount: indefinite
                                      tag: animateMotion
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: mpath
                                            xlink:href: "#path1"
                            - component: f7-row
                              config:
                                d: M40 -5 v10 c0 40 -10 35 -30 35 h-20
                                fill: none
                                id: path2
                                stroke: rgba(100, 150, 200, 0.8)
                                stroke-width: 2
                                tag: path
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0])
                                  > 0 &&
                                  Number.parseFloat(items[props.netzbezug].state.split("
                                  ")[0]) == 0) ? true : false'
                            - component: f7-row
                              config:
                                fill: rgba(100, 150, 200, 0.8)
                                r: 6
                                strokeWidth: 10
                                tag: circle
                                vectorEffect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.netzeinspeisung].state.split(" ")[0])
                                  > 0 &&
                                  Number.parseFloat(items[props.netzbezug].state.split("
                                  ")[0]) == 0) ? true : false'
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      calcMode: linear
                                      dur: 4s
                                      repeatCount: indefinite
                                      tag: animateMotion
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: mpath
                                            xlink:href: "#path2"
                            - component: f7-row
                              config:
                                d: M50, 0 v100
                                fill: none
                                id: path3
                                stroke: rgba(100, 150, 200, 0.8)
                                stroke-width: 2
                                tag: path
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) -
                                  (Number.parseFloat(items[props.netzeinspeisung].state.split("
                                  ")[0]) +
                                  Math.abs(Number.parseFloat(items[props.batterieleistung_neg].state.split("
                                  ")[0]))) > 0) ? true : false'
                            - component: f7-row
                              config:
                                fill: rgba(100, 150, 200, 0.8)
                                r: 6
                                strokeWidth: 10
                                tag: circle
                                vectorEffect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.pv_leistung].state.split(" ")[0]) -
                                  (Number.parseFloat(items[props.netzeinspeisung].state.split("
                                  ")[0]) +
                                  Math.abs(Number.parseFloat(items[props.batterieleistung_neg].state.split("
                                  ")[0]))) > 0) ? true : false'
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      calcMode: linear
                                      dur: 4s
                                      repeatCount: indefinite
                                      tag: animateMotion
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: mpath
                                            xlink:href: "#path3"
                            - component: f7-row
                              config:
                                d: M-5 50 l10 0 c40 0 35 10 35 50 l 0 20
                                fill: none
                                id: path4
                                stroke: rgba(100, 150, 200, 0.8)
                                stroke-width: 2
                                tag: path
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.netzbezug].state.split(" ")[0]) > 0) ?
                                  true : false'
                            - component: f7-row
                              config:
                                fill: rgba(100, 150, 200, 0.8)
                                r: 6
                                strokeWidth: 10
                                tag: circle
                                vectorEffect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.netzbezug].state.split(" ")[0]) > 0) ?
                                  true : false'
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      calcMode: linear
                                      dur: 4s
                                      repeatCount: indefinite
                                      tag: animateMotion
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: mpath
                                            xlink:href: "#path4"
                            - component: f7-row
                              config:
                                d: M 105 50 l -10 0 c -40 0 -35 10 -35 50 l 0 20
                                fill: none
                                id: path5
                                stroke: rgba(100, 150, 200, 0.8)
                                stroke-width: 2
                                tag: path
                                vector-effect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.batterieleistung_neg].state.split(" ")[0])
                                  > 0) ? true : false'
                            - component: f7-row
                              config:
                                fill: rgba(100, 150, 200, 0.8)
                                r: 6
                                strokeWidth: 10
                                tag: circle
                                vectorEffect: non-scaling-stroke
                                visible: '=(Number.parseFloat(items[props.batterieleistung_neg].state.split(" ")[0])
                                  > 0) ? true : false'
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      calcMode: linear
                                      dur: 4s
                                      repeatCount: indefinite
                                      tag: animateMotion
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            tag: mpath
                                            xlink:href: "#path5"
                - component: f7-block
                  config:
                    style:
                      align-items: center
                      display: flex
                      flex-direction: column
                      height: 110px
                      justify-content: center
                      margin-top: -10px
                      width: 110px
                  slots:
                    default:
                      - component: oh-icon
                        config:
                          color: orange
                          height: 110px
                          icon: sma_consumption_2
                      - component: Label
                        config:
                          style:
                            font-size: 25px
                            font-weight: bold
                            margin-top: -10px
                            text-align: center
                            width: 100px
                          text: =items[props.gesamtverbrauch].displayState
          - component: f7-col
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
            slots:
              default:
                - component: f7-block
                  config:
                    style:
                      align-items: center
                      display: flex
                      flex-direction: column
                      height: 110px
                      justify-content: center
                      margin-top: -40px
                      width: 110px
                  slots:
                    default:
                      - component: oh-link
                        config:
                          iconColor: red
                          iconF7: battery_0
                          iconSize: 33px
                          style:
                            font-size: 25px
                            font-weight: bold
                            white-space: nowrap
                          text: =items[props.batterylevel].state
                          visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) <
                            10) ? true : false'
                      - component: oh-link
                        config:
                          iconColor: orange
                          iconF7: battery_25
                          iconSize: 33px
                          style:
                            font-size: 25px
                            font-weight: bold
                            white-space: nowrap
                          text: =items[props.batterylevel].state
                          visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >=
                            10 &&
                            Number.parseFloat(items[props.batterylevel].state.split("
                            ")[0]) < 75) ? true : false'
                      - component: oh-link
                        config:
                          iconColor: green
                          iconF7: battery_100
                          iconSize: 33px
                          style:
                            font-size: 25px
                            font-weight: bold
                            white-space: nowrap
                          text: =items[props.batterylevel].state
                          visible: '=(Number.parseFloat(items[props.batterylevel].state.split(" ")[0]) >=
                            75) ? true : false'
                      - component: oh-icon
                        config:
                          height: 110px
                          icon: sma_battery_2
                          style:
                            margin-top: -20px
                      - component: Label
                        config:
                          style:
                            color: '=(Number.parseFloat(items[props.batterieleistung_pos].state.split(" ")[0]) >
                              0) ? "red" : "green"'
                            font-size: 25px
                            font-weight: bold
                            margin-top: -10px
                            text-align: center
                            white-space: nowrap
                            width: 100px
                          text: =Math.abs(Number.parseFloat(items[props.batterieleistung_pos].state.split("
                            ")[0])) + ' ᵂ'
                          visible: '=(Number.parseFloat(items[props.batterieleistung_pos].state.split(" ")[0])
                            !== 0) ? true : false'

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 9. Jun 2025 00:00
von udo1toni
Darf ich hier einmal darauf hinweisen, dass die beiden Werte nicht in Items ankommen, sondern in Channels? Und wenn Du zwei Channels hast, welche jeweils einen positiven Wert oder 0 liefern, sollte es reichen, beide Channel mit einem Item zu verlinken. Der Trick besteht dann darin, jeweils ein Inline Script als Profile zu nutzen. Im einen Channel sorgt das Inline Script dafür, dass der Wert nur dann übernommen wird, wenn er größer 0 ist.
Im anderen Channel gilt das gleiche, allerdings wird der Wert vorher mit -1 multipliziert.
Wichtig für den Hinterkopf: Der Status wird immer als String übergeben, entsprechend muss man den Input evtl. per parse.float in eine Zahl umwandeln.
Ungetestet: DSL|if(parse.float(input)> 0 ) - parse.float(input) für den negativ-Wert.

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 11. Jun 2025 17:15
von mad-mike
Der Trick besteht dann darin, jeweils ein Inline Script als Profile zu nutzen.
Aber wie muss man dies doch gleich machen?

Macht man das über die Text files, oder über die UI??

Ich kann auch mit der Doku nichts anfangen... :oops:

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 11. Jun 2025 20:51
von udo1toni
Inline -> Das Script wird direkt übergeben. Das Script ist kurz genug (siehe ungetestete Zeile)
Soweit ich weiß, kannst Du bei Modbus innerhalb des Channels keine Transformation durchführen, deshalb muss die Transformation im Profile erfolgen.
Wenn Du über die UI konfigurierst, wählst Du DSL als Scriptsprache aus und schreibst die Codezeile (mit Pipe) in das to Item Script Feld. Über eine Items-Datei sähe das so aus (ohne Gewähr):

Code: Alles auswählen

Number:Power AkkuLoad "Akku Leistung" {channel="inChannel"[profile="transform:DSL",toItemScript="|if(parse.float(input)> 0 ) - parse.float(input)"],
                                       channel="outChannel"[profile="transform:DSL",toItemScript="|if(parse.float(input)> 0 ) parse.float(input)"],
                                       unit="W", stateDescription=""[pattern="%.3f kW"]} 
Die Umbrüche hier nur wegen der Lesbarkeit, natürlich kannst Du das formatieren wie es Dir beliebt.

Da modbus meines Wissens selbst keine Unit unterstützt, muss die angegebene Unit der gelieferten Unit entsprechen. Im Pattern kannst Du aber jede passende Unit verwenden, d.h. die Ausgabe sollte automatisch korrekt sein. Das Widget dürfte unit-aware sein, weil die meisten Bindings inzwischen eine Unit liefern.

Wahlweise könntest Du die beiden Scripte natürlich auch in Dateien speichern und diese angeben, aber da es ja nur eine Zeile ist und Du im Zweifel zwei Scripte benötigst, ist das etwas umständlich.

Re: 2 Number item Verbinden zu einem (neg pos Werte)

Verfasst: 14. Jun 2025 17:44
von mad-mike

Code: Alles auswählen

2025-06-14 17:33:21.133 [ERROR] [.module.script.profile.ScriptProfile] - Failed to process script '|if(parse.float(input)> 0 ) - parse.float(input)': if( ___ parse. ___ float(input)> 0 ) -  ___ parse. ___ float(input)

   1. The method float(String) is undefined for the type Duration; line 1, column 9, length 5

   2. The method float(String) is undefined for the type Duration; line 1, column 35, length 5

   3. Invalid number of arguments. The method parse(CharSequence) is not applicable without arguments; line 1, column 3, length 5

   4. Invalid number of arguments. The method parse(CharSequence) is not applicable without arguments; line 1, column 29, length 5

2025-06-14 17:33:21.135 [ERROR] [.module.script.profile.ScriptProfile] - Failed to process script 'DSL|if("parse.float(input) > 0 ) - parse.float(input)"': Could not get script for UID 'DSL|if("parse.float(input) > 0 ) - parse.float(input)"'.



so ganz will das noch nicht :oops: