[Guide] Lag din egen Custom motion flow

Jeg har laget et eksempel på hvordan folk kan sette opp egen flow for å slå på lys ved bevegelse.

Kommenter gjerne om det er noe dere ikke forstår, eller burde omformuleres eller noe.

5 Likes

For å sette en statisk % ved første bevegelse etter modus er endet til home kan denne flowen brukes :slight_smile:

{
  "Id": "rkVqSnXehw2w52K",
  "ClassId": "Nqo6aLFaaFoKgW7",
  "Author": "espenh.no",
  "Version": 0,
  "CreatedAt": "2020-09-15T16:23:07.942061947+02:00",
  "UpdatedAt": "2020-09-15T16:35:08.463045152+02:00",
  "Name": "sensor_presence automations",
  "Group": "sensor_presence",
  "Description": "",
  "Nodes": [
    {
      "Id": "1",
      "Type": "trigger",
      "Label": "sensor_presence",
      "SuccessTransition": "8",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:evt/rt:dev/rn:zw/ad:1/sv:sensor_presence/ad:49_0",
      "Service": "sensor_presence",
      "ServiceInterface": "evt.presence.report",
      "Config": {
        "InputVariableType": "",
        "IsValueFilterEnabled": false,
        "LookupServiceNameAndLocation": false,
        "PropFilterName": "",
        "PropFilterValue": "",
        "RegisterAsVirtualService": false,
        "Timeout": 0,
        "ValueFilter": {
          "Value": true,
          "ValueType": ""
        },
        "ValueJPath": "",
        "ValueJPathResultType": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": null
      },
      "Ui": {
        "nodeType": "",
        "x": 702,
        "y": 118
      }
    },
    {
      "Id": "2",
      "Type": "action",
      "Label": "out_lvl_switch ON (Last known value)",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:32_1",
      "Service": "out_lvl_switch",
      "ServiceInterface": "cmd.binary.set",
      "Config": {
        "DefaultValue": {
          "Value": true,
          "ValueType": "bool"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 400,
        "y": 878
      }
    },
    {
      "Id": "4",
      "Type": "wait",
      "Label": "wait 10 min",
      "SuccessTransition": "5",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": 600000,
      "Ui": {
        "nodeType": "",
        "x": 596,
        "y": 876
      }
    },
    {
      "Id": "5",
      "Type": "action",
      "Label": "out_lvl_switch OFF",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:32_1",
      "Service": "out_lvl_switch",
      "ServiceInterface": "cmd.binary.set",
      "Config": {
        "DefaultValue": {
          "Value": false,
          "ValueType": "bool"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 594,
        "y": 1030
      }
    },
    {
      "Id": "6",
      "Type": "if",
      "Label": "if presence = true",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": false,
            "LeftVariableName": "",
            "Operand": "eq",
            "RightVariable": {
              "Value": true,
              "ValueType": "bool"
            }
          }
        ],
        "FalseTransition": "7",
        "TrueTransition": "2"
      },
      "Ui": {
        "nodeType": "",
        "x": 409,
        "y": 723
      }
    },
    {
      "Id": "7",
      "Type": "if",
      "Label": "if presence = false",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": false,
            "LeftVariableName": "",
            "Operand": "eq",
            "RightVariable": {
              "Value": false,
              "ValueType": "bool"
            }
          }
        ],
        "FalseTransition": "",
        "TrueTransition": "4"
      },
      "Ui": {
        "nodeType": "",
        "x": 598,
        "y": 730
      }
    },
    {
      "Id": "8",
      "Type": "if",
      "Label": "if home",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": true,
            "LeftVariableName": "fh.home.mode",
            "Operand": "eq",
            "RightVariable": {
              "Value": "home",
              "ValueType": "string"
            }
          }
        ],
        "FalseTransition": "9",
        "TrueTransition": "16"
      },
      "Ui": {
        "nodeType": "",
        "x": 498,
        "y": 343
      }
    },
    {
      "Id": "9",
      "Type": "if",
      "Label": "if sleep",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": true,
            "LeftVariableName": "fh.home.mode",
            "Operand": "eq",
            "RightVariable": {
              "Value": "sleep",
              "ValueType": "string"
            }
          }
        ],
        "FalseTransition": "",
        "TrueTransition": "10"
      },
      "Ui": {
        "nodeType": "",
        "x": 941,
        "y": 329
      }
    },
    {
      "Id": "10",
      "Type": "if",
      "Label": "if presence = true",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": false,
            "LeftVariableName": "",
            "Operand": "eq",
            "RightVariable": {
              "Value": true,
              "ValueType": "bool"
            }
          }
        ],
        "FalseTransition": "13",
        "TrueTransition": "12"
      },
      "Ui": {
        "nodeType": "",
        "x": 857,
        "y": 560
      }
    },
    {
      "Id": "12",
      "Type": "action",
      "Label": "out_lvl_switch cmd.lvl.set 10%",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:32_1",
      "Service": "out_lvl_switch",
      "ServiceInterface": "cmd.lvl.set",
      "Config": {
        "DefaultValue": {
          "Value": 10,
          "ValueType": "int"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 865,
        "y": 724
      }
    },
    {
      "Id": "13",
      "Type": "if",
      "Label": "if presence = false",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": {
        "Expression": [
          {
            "BooleanOperator": "",
            "LeftVariableIsGlobal": false,
            "LeftVariableName": "",
            "Operand": "eq",
            "RightVariable": {
              "Value": false,
              "ValueType": "bool"
            }
          }
        ],
        "FalseTransition": "",
        "TrueTransition": "14"
      },
      "Ui": {
        "nodeType": "",
        "x": 1069,
        "y": 558
      }
    },
    {
      "Id": "14",
      "Type": "wait",
      "Label": "wait 2 min",
      "SuccessTransition": "15",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "Config": 120000,
      "Ui": {
        "nodeType": "",
        "x": 1066,
        "y": 720
      }
    },
    {
      "Id": "15",
      "Type": "action",
      "Label": "out_lvl_switch OFF",
      "SuccessTransition": "",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:32_1",
      "Service": "out_lvl_switch",
      "ServiceInterface": "cmd.binary.set",
      "Config": {
        "DefaultValue": {
          "Value": false,
          "ValueType": "bool"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 1066,
        "y": 882
      }
    },
    {
      "Id": "16",
      "Type": "if",
      "Label": "if firstMovement",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "SuccessTransition": "",
      "ErrorTransition": "",
      "Config": {
        "TrueTransition": "17",
        "FalseTransition": "6",
        "Expression": [
          {
            "Operand": "eq",
            "LeftVariableName": "firstMovement",
            "LeftVariableIsGlobal": true,
            "RightVariable": {
              "Value": true,
              "ValueType": "bool"
            },
            "BooleanOperator": ""
          }
        ]
      },
      "Ui": {
        "x": 309,
        "y": 531,
        "nodeType": ""
      }
    },
    {
      "Id": "17",
      "Type": "action",
      "Label": "out_lvl_switch 40%",
      "SuccessTransition": "18",
      "TimeoutTransition": "",
      "ErrorTransition": "",
      "Address": "pt:j1/mt:cmd/rt:dev/rn:zw/ad:1/sv:out_lvl_switch/ad:32_1",
      "Service": "out_lvl_switch",
      "ServiceInterface": "cmd.lvl.set",
      "Config": {
        "DefaultValue": {
          "Value": 40,
          "ValueType": "int"
        },
        "IsVariableGlobal": false,
        "Props": {},
        "RegisterAsVirtualService": false,
        "ResponseToTopic": "",
        "VariableName": "",
        "VirtualServiceGroup": "",
        "VirtualServiceProps": {}
      },
      "Ui": {
        "nodeType": "",
        "x": 121,
        "y": 706
      }
    },
    {
      "Id": "18",
      "Type": "set_variable",
      "Label": "set false firstMovement",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "SuccessTransition": "",
      "ErrorTransition": "",
      "Config": {
        "Name": "firstMovement",
        "UpdateGlobal": true,
        "UpdateInputMsg": false,
        "DefaultValue": {
          "Value": 0,
          "ValueType": "bool"
        }
      },
      "Ui": {
        "x": 116,
        "y": 867,
        "nodeType": ""
      }
    },
    {
      "Id": "20",
      "Type": "set_variable",
      "Label": "set true firstMovement",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "SuccessTransition": "",
      "ErrorTransition": "",
      "Config": {
        "Name": "firstMovement",
        "UpdateGlobal": true,
        "UpdateInputMsg": false,
        "DefaultValue": {
          "Value": true,
          "ValueType": "bool"
        }
      },
      "Ui": {
        "x": 155,
        "y": 297,
        "nodeType": ""
      }
    },
    {
      "Id": "21",
      "Type": "vinc_trigger",
      "Label": "Home event trigger",
      "Address": "",
      "Service": "",
      "ServiceInterface": "",
      "SuccessTransition": "20",
      "ErrorTransition": "",
      "Config": {
        "Timeout": 0,
        "ValueFilter": "home",
        "IsValueFilterEnabled": true,
        "EventType": "mode"
      },
      "Ui": {
        "x": 157,
        "y": 145,
        "nodeType": ""
      }
    }
  ],
  "Settings": null,
  "IsDisabled": false,
  "IsDefault": false,
  "ParallelExecution": "keep_last"
}
3 Likes

Jeg har custom flows for lys ved bevegelse hvor jeg også tar med lux, slik at ikke lyset slår seg på dersom det er lyst i rommet fra før. Flowen bygger på den du har laget @espen, men med noen tillegg. Dette fungerer nå 95%, men jeg har et problem. Det skjer dersom det er bevegelse i rommet etter at eventet “presence = false” har blitt fyrt av, og man står i “wait” modus. Da blir ikke bevegelse fanget opp, og etter et visst antall minutter slår lyset seg av selv om man er i rommet.

Er dette en såkalt busy wait; altså at flowen ikke reagerer på andre events mens den venter?
Har forsøkt litt forskjellig, men får samme resultat uansett.

Har du valgt “keep new instance”?

Nei, jeg kjører i parallell. Jeg har flere triggere og variabler som blir oppdatert ifm lux, så måtte det for å få det til å fungere. Mener jeg har tatt høyde for parallell kjøring, men akkurat den “wait”-en gjør ikke som forventet…

Aha! Ja da blir ikke wait noden avbrutt ved ny bevegelse nei. Det jeg har gjort er at jeg har en egen flow med triggere som setter variabler. Så bruker jeg de i “lysflowen” som har “keep new instances”.
Usikker på om det finnes noen annen måte å gjøre det på for å få wait noden til å avbryte ved ny bevegelse🤔

@nilsml “Keep new instance” er nøkkelen her. Ellers kan du risikera at det blir kjørt veldig mange flows i parallell - kanskje fleire enn hubben og spesielt z-wave nettverket ditt klarer å handtera. Løysinga er då å splitta opp flowen du har no i fleire mindre, og få dei til å samhandla (vha globale variabler og kreativ bruk av triggere).

(Apropos dette - skulle gjerne ha hatt muligheit til å fyra i gang flows ved oppdatering av global variabel - har ikkje kjørt meg fast endå men ser at det kan vera nyttig :nerd_face:)

Takker for tips. Får sette meg ned og splitte opp flow i flere og bruke globale variabler. Men vil jo anta at hver flow avsluttes så snart den har gjort sitt, og på den måten så blir det ikke så mange parallelle. Har ikke hatt noe problemer med det så langt ihvertfall. Kun det med wait-noden. Men flere flows gjør kanskje feilsøkingen noe enklere uansett, så tror det er et godt tips.

1 Like

Jeg får ikke denne til å virke. Flowen slår lys ved bevegelse, men etter satt tid (10 min) slås det av.

Egentlig er det nå verre enn med standard “trigger ved bevegelse i rom”, for når lyset nå slår seg av hjelper det ikke med ny bevegelse. Jeg kan hoppe og vifte foran sensor, og ser det lyser grønt i LED-en, men lyset slår seg ikke på. Etter et antall minutter slår lyset seg på ved bevegelse.

Hva gjør jeg feil?

Kan du åpne source code og se hva “ParallelExecution” er satt til?

Skal stå til:
“ParallelExecution”: “keep_last”

Kan også endres ved å trykke på pensel øverst hvor du kan redigere navn

"ParallelExecution": "keep_last"

Bilde 21.10.2020 klokken 23.09

Kan du dele flowen du bruker, så må jeg nesten lese gjennom om det er en feil et sted

Eg brukar ei lett modifisera utgåve av den flowen som gjer at ein kan setje ljoset til ein statisk dimmeverdi ved fyrste rørsle etter at huset er sett i heimemodus. Det fungerer som ein draum, med eitt unntak:

Me har ein modusbrytar på soverommet. Som regel brukar me denne til å byte om frå nattmodus til heimemodus når me står opp om morgonen. Me har eit nokså omfattande Z-Wave-nettverk, så denne overgangen går ikkje akkurat på sekundet, for å seie det slik. :wink:

Det som difor ofte skjer er at når ein av oss set huset i heimemodus og så går rett ut i gangen og inn på badet så får ikkje systemet “tenkt seg om”, og me endar med at ljoset ikkje får skrudd seg opp til dagnivå. Eg går ut frå at dette kjem av at med ein gong me bevegar oss ut i gangen så vert “firstMovement” sett til “false” der og då, men at den delen av flowen som styrer ljos av/på og dimmeverdi ikkje kjem gjennom all støyen på nettverket.

Når systemet får roa seg ned så endar me opp med at ljoset tenner seg på nattnivå, og at me då må dimme opp manuelt.

Eg har tenkt på ulike måtar å løyse dette på. Den beste ideen eg har så langt er å leggje inn ein “wait”-node på kanskje eitt minutt eller to (her lyt eg prøve meg fram) før “firstMovement” vert sett til “false”.

Eg vil tru at dette løyser problemet? Eller er det nokon andre som har ei meir elegant løysing? :slight_smile:

1 Like

Flott å høre den fungerer bra “til vanlig” :wink:
Å legge inn en wait node kan fungere greit det også :slight_smile:
Det er også mulig å redigere flow for modusbryteren, som kan trigge “pre-Home mode” innstillinger, med en wait for å deretter kjøre hjemme modus. Om du bruker Futurehome sin modusbryter, så kan den flowen bli overskrevet ved ny inkluderingsrapport (f.eks trykkes på “services” i thingsplex for den enheten).

2 Likes

No er me inne på eit nyttig tema! Har akkurat samme utfordring som @Torfinn, og kunne dessutan gjerne tenkt meg å vita meir om korleis hubben prioriterar når den skal skifta modus. Har ein teori om at den treige responsen på feks belysning ved modusbytte (>1-2 minutt) kan skuldast batteridrevne einingar, feks radiatorstyring, som bruker lang tid på å senda respons. Men har ikkje fått sjekka teorien. I dette tilfellet er det ikkje aktuelt med “pre-home” innstillingar, då eg ynskjer at mest mulig skal la seg konfigurera i appen…

1 Like

Berre til informasjon så fungerer det fint som berre det med ein “wait”-node slik som føreslege ovanfor. :blush::+1: Eg gjekk for to minutt, og då er problemet borte for vår del.

1 Like

Bra guide, takk Espen!

Ønsker å gjøre noe slikt: “Hvis bevegelse ikke er registrert på X døgn, sett hjem-modus til vacation”; hva er en enkel fremgangsmåte?

Jeg finner ikke noen måte å bruke “motion sensor presence state/presence report for X amount of time” funksjonalitet. Forslag til hvordan jeg kan løse dette? Har vært inne på tanken om å lage en “Virtual Device” eller “Input variable”, men håper det finnes en penere kode for å komme til mål :slight_smile:

Hvordan blir man Node-RED betatester? Bruker Node-RED i et annet hjem, der finnes funksjonaliteten (om state blir logget) :blush:

1 Like

Oi, den var ekstrem! (Høyrest ut som ein flow for fruen i huset). Eg trur nok ein slik flow vil kunna skapa meir problem enn den løyser, og koden vil nok kunna bli ganske grisete (Wait noden tillet nok ikkje så lang forsinkelse) - om du forklarer behovet ditt så kan me kanskje hjelpa deg å finna ei meir elegant løysing?

Node red krev at du set opp ein eigen “server” - ein PC som alltid står på, feks Raspberry Pi eller liknande, men interfacet kan kven som helst aktivera i FH appen: Hub-innstillinger → Lokalt API oppsett.

1 Like

Caset er en flerbrukshuset, med opptil flere uten noen særlig teknisk interesse :sweat_smile:

Det skjer flere ganger per halvår at hjem-modus blir stående på «Home» selv om alle er bortreist.

Aha, takk! API via MQTT du mener da?

Aha :slightly_smiling_face:
Like gjerne som bevegelsessensor (kan fort gå tom for batteri uten at nokon reagerer på det) er kanskje å kobla opp mot dørlås, eller kva med å kobla opp mot HAN sensor (viss fleirbrukshuset ikkje blir brukt vil det sannsynligvis gå an å sjå det på strømbruken?) Berre nokre idear… Om du er bestemt på ein tidsforsinkelse som er lenger enn max for wait noden så tenkjer eg du sannsynligvis vil måtta henta ut ein “timestamp” frå vilkårleg event (transform) til ein global variabel også gjera regelmessig sjekk på kor gammal timestampen er blitt. Men dette er nok upløyd mark så lykke til :slightly_smiling_face: