Tthingsplex - IF Switch og variabler

Noen som vet om der er mulig i Thingsplex å la en «IF Switch» sjekke mot en global variabel istedenfor å taste inn et tall ? Ser ikke ut til at man kan velge en variabel under «value» på høyre side. Ønsker å sjekke mot float variabelen «Power_Limit»

2 Likes

Er mulig, men du må gå via ein omveg via Transform node. La den ta følgjande kalkulasjon og lagra den i ny “In memory” variabel “Alarm_margin”, “EV_Margin” e.l. (navnet på variabelen vel du naturligvis sjølv - eksempla er egna i tilfelle du ynskjer å få notifikasjon på mobilen, og slå av feks elbilladeren i samme flow, men med forskjellige alarmgrenser):

Alarm_Limit-input
Alarm_Limit og EV_Limit kan ikkje vera “In memory”, for i motsetning til “margin” ynskjer du å beholda disse variablane om hubben blir restarta e.l.

Deretter set du opp den nye variabelen i IF noden, med condition >0 og drar ein strek frå den grønne prikken (dvs “true”) til valgfri actionnode.

Her er eit enkelt eksempel på ein ganske lik flow som den du prøver å få til:

2 Likes

Tusen takk for tilbakemelding, men må si jeg ikke henger helt med her.
Ser ikke helt hvilke variabler man skal ha i Transform noden for at den skal returnere >0 hvis avlest effekt er større en Limit. Avlest effekt fra Tiber puls ser ut til å havne i «Trigger variable» ønsker å sjekke denne mot: «Power_Limit» som er en global variabel. Da kan man enkelt endre denne til f.eks 5000 eller 10000. Egentlig er det bare å sjekke om: «Trigger variable» - «Power_Limit» > 0

Jeg har laget en flow og har fått den til å trigge som jeg ønsker, men da må man skrive inn verdien i «IF Condition» utrykket. Det er ikke så elegant da jeg tenker videre at strømtrekket må være større en «Power_Limit» i noen minutter før man begynner å skru av ting. Fikk det til ved å inkrementere en variabel.

Ellers tenkte jeg å sende en «Push Notification» hvis systemet blir trigget, med effekten i meldingen, men det fikk jeg ikke til.

Tenkte jeg kunne lese effekten til forskjellige varmekabler etter en prioriteringsliste, men får ikke lest effekt:
Sender: basic cmd.lvl.get_report pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1
Leser: basic evt.lvl.report pt:j1/mt:evt/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1

Men det ser ikke ut til å fungere. Noen tips ?

Her er bilde av Flowen jeg har begynt å leke med:

{
  "Id": "9f221bf0-5a11-11ed-bb55-cd7639cfff17",
  "ClassId": "9f221bf0-5a11-11ed-bb55-cd7639cfff17",
  "Author": "xxxxxxxxxx",
  "Version": 0,
  "CreatedAt": "2022-11-01T18:18:44.911381Z",
  "UpdatedAt": "2022-11-20T22:20:20.658631005+01:00",
  "Name": "TEST Puls > 750W, Accumulated_Power > 10000 set tmp til 20, les fra termostat",
  "Group": "sensor_wattage",
  "Description": "send oppvarming settpunkt på  Bad 2 etg Termostat   til 20 og etter 7 minutter send oppvarming settpunkt på  Bad 2 etg Termostat   til 23 ",
  "Nodes": [
    {
      "Id": "90",
      "Type": "trigger",
      "Label": "når watt verdien av Bad 2 etg Termostat  er høyere enn 750W",
      "SuccessTransition": "91",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:evt/rt:dev/rn:tibber/ad:1/sv:meter_elec/ad:2d243b4a-8b93-4016-99b5-aeabf1b908b0",
      "Service": "meter_elec",
      "ServiceInterface": "evt.meter.report",
      "Config": {
        "InputVariableType": null,
        "IsValueFilterEnabled": false,
        "LookupServiceNameAndLocation": false,
        "PropFilterName": "unit",
        "PropFilterValue": "W",
        "RegisterAsVirtualService": false,
        "Timeout": 0,
        "ValueFilter": {
          "Value": "{'PropFilterName': 'unit', 'PropFilterValue': 'W'}",
          "ValueType": ""
        },
        "ValueJPath": null,
        "ValueJPathResultType": null,
        "VirtualServiceGroup": "ch_0",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "papp": {
          "customValues": null,
          "nodeId": "18",
          "nodeName": "wattage",
          "nodeType": "wattage"
        },
        "x": 434,
        "y": 224
      },
      "TypeAlias": "Trigger",
      "LastValue": "1135 W"
    },
    {
      "Id": "91",
      "Type": "if",
      "Label": "> 3000",
      "SuccessTransition": "92",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "tpflow",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": false,
            "LeftVariableName": "",
            "Operand": "gt",
            "RightVariable": {
              "Value": 3000,
              "ValueType": "float"
            }
          }
        ],
        "FalseTransition": "107",
        "TrueTransition": "95"
      },
      "Ui": {
        "nodeType": "",
        "papp": {
          "customValues": null,
          "nodeId": null,
          "nodeName": "If",
          "nodeType": "wattage"
        },
        "x": 430,
        "y": 401
      },
      "TypeAlias": "If condition"
    },
    {
      "Id": "92",
      "Type": "action",
      "Label": " Bad 2 etg Termostat til 20",
      "SuccessTransition": "93",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:thermostat/ad:9_1",
      "Service": "thermostat",
      "ServiceInterface": "cmd.setpoint.set",
      "Config": {
        "DefaultValue": {
          "Value": {
            "temp": "20",
            "type": "heat",
            "unit": "C"
          },
          "ValueType": "str_map"
        },
        "IsVariableGlobal": false,
        "LookupServiceNameAndLocation": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": null,
        "VariableName": "",
        "VirtualServiceGroup": "ch_0",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "papp": {
          "customValues": null,
          "nodeId": "18",
          "nodeName": "device",
          "nodeType": "deviceAction"
        },
        "x": 117,
        "y": 1835
      },
      "TypeAlias": "Action"
    },
    {
      "Id": "93",
      "Type": "wait",
      "Label": "30 sek",
      "SuccessTransition": "112",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": 30000,
      "Ui": {
        "nodeType": "",
        "papp": {
          "customValues": null,
          "nodeId": null,
          "nodeName": "wait",
          "nodeType": "deviceTimeout"
        },
        "x": 110,
        "y": 2007
      },
      "TypeAlias": "Delay"
    },
    {
      "Id": "95",
      "Type": "set_variable",
      "Label": "To Current_power(float)",
      "SuccessTransition": "105",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "DefaultValue": {
          "Value": 0,
          "ValueType": ""
        },
        "IsVariableInMemory": false,
        "Name": "Current_power",
        "UpdateGlobal": true,
        "UpdateInputMsg": false
      },
      "Ui": {
        "nodeType": "",
        "x": 432,
        "y": 566
      },
      "TypeAlias": "Set variable"
    },
    {
      "Id": "97",
      "Type": "action",
      "Label": "Les effekten på badet",
      "SuccessTransition": "104",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1",
      "Service": "basic",
      "ServiceInterface": "cmd.lvl.get_report",
      "Config": {
        "DefaultValue": {
          "Value": "",
          "ValueType": "null"
        },
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 231,
        "y": 1297
      },
      "TypeAlias": "Action"
    },
    {
      "Id": "104",
      "Type": "receive",
      "Label": "",
      "SuccessTransition": "111",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:evt/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1",
      "Service": "basic",
      "ServiceInterface": "evt.lvl.report",
      "Config": {
        "IsValueFilterEnabled": false,
        "LookupServiceNameAndLocation": false,
        "RegisterAsVirtualService": false,
        "Timeout": 120,
        "ValueFilter": {
          "Value": "{'PropFilterName': 'unit', 'PropFilterValue': 'W'}",
          "ValueType": "object"
        },
        "VirtualServiceGroup": "ch_0",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 219,
        "y": 1467
      },
      "TypeAlias": "Wait event"
    },
    {
      "Id": "105",
      "Type": "transform",
      "Label": "Accumulated_Power + Current_power",
      "SuccessTransition": "110",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": "Accumulated_Power + Current_power",
        "IsLVariableGlobal": true,
        "IsRVariableGlobal": false,
        "IsTargetVariableGlobal": true,
        "IsTargetVariableInMemory": false,
        "LVariableName": "Current_power",
        "RValue": {
          "Value": 0,
          "ValueType": "int"
        },
        "RVariableName": "",
        "Rtype": "var",
        "TargetVariableName": "Accumulated_Power",
        "TargetVariableType": "float",
        "Template": "",
        "TransformType": "calc",
        "ValueMapping": [],
        "XPathMapping": []
      },
      "Ui": {
        "nodeType": "",
        "x": 425,
        "y": 746
      },
      "TypeAlias": "Transform"
    },
    {
      "Id": "107",
      "Type": "set_variable",
      "Label": "Accumulated_Power = 0",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "DefaultValue": {
          "Value": 0,
          "ValueType": "float"
        },
        "IsVariableInMemory": false,
        "Name": "Accumulated_Power",
        "UpdateGlobal": true,
        "UpdateInputMsg": false
      },
      "Ui": {
        "nodeType": "",
        "x": 764,
        "y": 558
      },
      "TypeAlias": "Set variable"
    },
    {
      "Id": "108",
      "Type": "set_variable",
      "Label": "Accumulated_Power = 0",
      "SuccessTransition": "97",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "DefaultValue": {
          "Value": 0,
          "ValueType": "float"
        },
        "IsVariableInMemory": false,
        "Name": "Accumulated_Power",
        "UpdateGlobal": true,
        "UpdateInputMsg": false
      },
      "Ui": {
        "nodeType": "",
        "x": 269,
        "y": 1109
      },
      "TypeAlias": "Set variable"
    },
    {
      "Id": "110",
      "Type": "if",
      "Label": "Accumulated_Power > 10 000",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": true,
            "LeftVariableName": "Accumulated_Power",
            "Operand": "gt",
            "RightVariable": {
              "Value": 10000,
              "ValueType": "float"
            }
          }
        ],
        "FalseTransition": "",
        "TrueTransition": "108"
      },
      "Ui": {
        "nodeType": "",
        "x": 412,
        "y": 929
      },
      "TypeAlias": "If condition"
    },
    {
      "Id": "111",
      "Type": "if",
      "Label": "> 750 Watt",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "SuccessTransition": "",
      "ErrorTransition": "",
      "Config": {
        "TrueTransition": "92",
        "FalseTransition": "",
        "Expression": [
          {
            "Operand": "eq",
            "LeftVariableName": "",
            "LeftVariableIsGlobal": false,
            "RightVariable": {
              "Value": 750,
              "ValueType": "int"
            },
            "BooleanOperator": ""
          }
        ]
      },
      "Ui": {
        "x": 206,
        "y": 1650,
        "nodeType": ""
      },
      "TypeAlias": "If condition"
    },
    {
      "Id": "112",
      "Type": "action",
      "Label": "Bad 2 etg Termostat til 23",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:thermostat/ad:9_1",
      "Service": "thermostat",
      "ServiceInterface": "cmd.setpoint.set",
      "Config": {
        "DefaultValue": {
          "Value": {
            "temp": "23",
            "type": "heat",
            "unit": "C"
          },
          "ValueType": "str_map"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "ch_0",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 104,
        "y": 2198
      },
      "TypeAlias": "Action"
    }
  ],
  "Settings": null,
  "IsDisabled": true,
  "IsDefault": false,
  "ParallelExecution": "keep_first"
}

Innbiller meg eg har svart på spørsmålet, har eg ikkje? :thinking:

Er ikkje heilt rett fram å få til, men ser ut som du er på god veg til å finna ei kreativ løysing på problemet.

Denne er heller ikkje heilt rett fram, men mulig du finn noko inspirasjon her:

Jo, du kom med noen tips. Det er bare jeg som ikke helt forstår hvordan kalkulasjonen i Transform noden fungerer. I eksempelet er det som expression skrevet input-meter_old. Er det her skrevet en formel? Kalkulasjonen skal jo resultere i at meter_increment skal bli >0 hvis strømtrekket er over limit. Sammenlignet med andre programmeringsspråk er vel ikke dette helt intuitivt ?

Kalkulasjonen i eksempelet over er ikkje relevant for din case, men framgangsmåten er den samme. Du må bytta ut uttrykket input-meter_old med Alarm_Limit-input - eller i ditt konkrete eksempel Power_Limit-input.

Takk for info. Da ble det litt tid til FH igjen, og etter å ha studert eksemplene fikk jeg til ønsket funksjonalitet i Calculate transformen. Jeg var litt forvirret av «Left variable», «Trigger variable» og «input». Fikk ellers til å skrive innholdet av en variabel i «timeline» med ikke i «Push Notification».

Vel, da har jeg en annen utfordring: Ønsker å lese ut effekten fra gulv termostatene nede i en flow som trigges av høyt strømforbruk avlest fra Tibber Puls. Forstår man må sende kommandoen «cmd.lvl.get_report» i en «Action» node, deretter må man lese responsen i en «Wait fore Event» med kommandoen «evt.lvl.report". Dette var beskrevet her: Thingsplex tukler med variablene - #3 by Olaisene

Men jeg får ikke dette til å fungere, leser ikke effekten, og FH «henger». (Måtte restarte.)

Noen tips ?

Prøv først å kjøre manuelt , og verifiser at rele sender forbruk , eller om du må sende get commando .

Vel, i FH kan man se effekten når gulvet står på, så det fungerer som forventet.

Dette kan man også se i «Message Stream»

{

“serv”: “meter_elec”,

“type”: “evt.meter.report”,

“val_t”: “float”,

“val”: 1017.15997314453,

“props”: {

“unit”: “W

},

“tags”: null,

“src”: “-”,

“ver”: “1”,

“uid”: “e1c79f1a-38ce-490f-8f2f-884013bc33af”,

“topic”: “pt:j1/mt:evt/rt:dev/rn:zw/ad:1/sv:meter_elec/ad:9_1”

Hvis man lage en ny enkel flow og trigger på effekten fra det aktuelle gulvet fungerer det også.

Men jeg ønsker å lese av effekten til flere gulv nede i en sekvens, og da ser jeg noen skriver man må først sende «get_report» og deretter «Wait fore event»

Dette her jeg forsøkt, først en «Action»

Service : Generic basic (basic)

Functionality: Request level report (cmd.lvl.get_report)

Address: pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1

Deretter kjører jeg en «Wait fore event»

Service : Generic basic (basic)

Functionality : Generic level report (evt.lvl.report)

Address : pt:j1/mt:evt/rt:dev/rn:zw/ad:1/sv:basic/ad:9_1

Dette mener jeg skal være ganske likt eksempelet, men fungerer altså ikke.

Jeg anbefaler at du lager en flow som lagrer verdiene i en global variabel, istedenfor å “lese av nede i flowen!”

Vel, tanken var å ha kun en trigger i Flowen. For bedre oversikt å mindre resursbruk. Tenkte å Trigge når Tibber puls rapportere > 10kw (Current_Limit) i X antall minutter.

Så kan man lese effekten til forbrukere etter en prioritert liste og skru av inntil man er under ønsket verdi. (4 gulvtermostater, en varmepumpe og en VVB) Antok det var en enkel sak å lese ut effektforbruket fra enhetene.

Ser jo man får lest effektforbruket ved å lage en trigger, men da blir det mange triggere som starter denne Flowen. Kan jo skru av parallell kjøringen med det blir jo ikke så oversiktlig.

Hvis man skal lese av samtlige forbrukere men hver sin trigger og lagre resultatene i globale variable, hvordan ville du da håndtert dette for at ikke denne flowen skal bli startet hele tiden ? Det må da være bedre med kun en trigger å lese forbruks enhetene ved behov ?

Du har to typer HAN/AV PÅ enheter. De som sender uten å bli spurt , slik som HAB siste versjon , og de som må spørres først for så å svare .

HAN må du bare ta imot . De andre må du først be om rapport, så vente på svar . Da lager du en timer event som spør etter data , og som i samme flow har nodene som venter på svar .

Hvor ofte anbefales det da å kjøre denne timer event triggeren ? Må jo være sikker på at man har korrekte data når hoved sekvensen kjøres. Vil det si det er umulig å lese effektforbruket ved behov i hoved sekvensen ? Må lese fra 6 enheter. Vil alle trådene i Flowen bli eksekvert hver gang man får en trigger ?

Der er du inne på en artig sak. Du kan se på hver automasjon som en ett program med flere parallelle aktiviteter . Timer events sender “Send report” med jevne intervall, og og de andre ligger og lytter og fyrer når de ser svar i meldings buffer.

Laget for morro skyld en automasjon, som jeg kalte NOBOE_512 , som inneholder ett antall timer triggere , som skrur av og på ulike ting hver 4de time… dvs 6 time triggere som bare ligger og venter.

Triggere trigger ikke flow… triggere stopper flow opp , til noe skjer…

Igjen, jeg ønsker å lese effekten til de ulike forbrukeren når flowen kjøres, Effekten kan jo variere en del f.eks fra varmepumpa. Ellers hvis hoved flowen er blitt trigget pga. høyt strømforbruk totalt sett (tibber pulse) ønsker jeg jo at alt skal kjøres umidelbart.

Sanntid er definert som med en tidsforsinkelse som i forhold til aktiviteten er neglisjerbar.
Dette defineres ofte som en tidsforsinkelse som er ca 1/10 av tidskonstanten på prosessen du måler.

Om du har en varmepumpe som står på i 5-15 minutter , vil avlesning en gang i minuttet , gi deg en sann nok verdi for alle formål.

Så kan du lese av 2 ting , NÅ EFFEKT i Watt , og akkumulert effekt i kWh . Om du leser kWh hvert 5 minutt og tar diferanse mellom to siste målinger , får du også ett meget godt estimat.

Så , til det med øyeblikk, jeg gjør noe av det samme , om for høyt , skru av det som er på , og skru tilbake etter på … Men det gjør jeg på den måten at jeg har en TRINÆR GLOBAL VARIABEL …

0 Forbruk er AV
1 Forbruk er PÅ
2 Forbruk var PÅ men er satt av for å unngå overforbruk

Dermed følger globale variable enhetene. Samme gjør jeg med effekten på utvalget enheter , leser en gang i minuttet , og lagere W eller kWh , etter behov.

OK takk for svar Da forstår jeg det slik at det ikke er mulig å avlese effekten til den enkelte varmekilde nede i hoved sekvensen. Tanken hær er jo å skru ting av for ikke å komme over i neste trinn i effekt forbruket. Da må man jo selvfølgelig skru ting på etter en tid.

Da bør man vel skru av parallell kjøringen å gå for Keep last ? Tibber puls triggeren skjøres jo ca. hvert 10sec. Da blir den en hovedsekvens + 6 andre triggere som leser effekten fra varmekilder og lagrer dem i globale variabler. Da forstår jeg det er fornuftig å tids trigge disse hvert minutt. Hvordan vil dette fungere, vil disse triggerene starte eksekveringen av hoved sekvensen også ? Eller blir dette å se til som 7 uavhengige tråder som lever hvert sitt liv ?

Du kan avlese effekten , i hoved sekvensen , med en tidskonstant som for alle praktiske formål ikke betyr noe som helst. Du må lese via global variable og en input flow .

Dette er ett av de viktigste prinsippene i sanntidsprogrammering. Du mu huske på at koden, om du ikke har flere kjerner som kjører i parallell , til syvende og sist kjører en linje av gangen. ALDRI alle linjer samtidig.

Men du må forholde deg til om du må be om rapport , eller får rapport fra enhetene, og så bygge en beslutnings matrise ( Globale variable ) som oppdateres hurtig nok, til at beslutninger blir rett.