LUA kod för badrum?

Post Reply
User avatar
Texan
Medlem
Posts: 169
Joined: 25 Dec 2015, 15:07
8

Hej,
Undrar ifall någon kan hjälpa mig med lua kod för mitt badrum.

Har följande;
2 fibaro rörelse/lux sensorer, en vid ingången till badrummet och en vid duschen.
1 fibaro dimmer2 som styr tak (spotlights)
1 fibaro switch som styr lampor vid spegel

Sensorn som sitter vid ingången tänkte jag skulle tända lamporna vid spegeln och tak när man kommer in i badrummet, och sensorn vid duschen ska hålla lamporna tända så länge man duschar.
Vid ljusa dagar så ska bara spegeln tändas men är det mörkare ute så skall även tak tändas till 100% och ifall det är ljusa dagar ska taket tändas till 100% om man duschar.
Sedan ifall man går upp på natten exempelvis mellan 23:30 och 5:30 så skall taket endast tändas upp 10% och spegeln ska inte tändas alls.
Och på natten kan det släckas efter 3 min inaktivitet, medans övrig tid kan det släckas efter 10 min.

Tack på förhand
jang
Medlem
Posts: 388
Joined: 05 Jan 2014, 00:44
10
Location: Stockholm

Texan wrote: 24 Apr 2019, 00:05 Hej,
Undrar ifall någon kan hjälpa mig med lua kod för mitt badrum.

Har följande;
2 fibaro rörelse/lux sensorer, en vid ingången till badrummet och en vid duschen.
1 fibaro dimmer2 som styr tak (spotlights)
1 fibaro switch som styr lampor vid spegel

Sensorn som sitter vid ingången tänkte jag skulle tända lamporna vid spegeln och tak när man kommer in i badrummet, och sensorn vid duschen ska hålla lamporna tända så länge man duschar.
Vid ljusa dagar så ska bara spegeln tändas men är det mörkare ute så skall även tak tändas till 100% och ifall det är ljusa dagar ska taket tändas till 100% om man duschar.
Sedan ifall man går upp på natten exempelvis mellan 23:30 och 5:30 så skall taket endast tändas upp 10% och spegeln ska inte tändas alls.
Och på natten kan det släckas efter 3 min inaktivitet, medans övrig tid kan det släckas efter 10 min.

Tack på förhand
Jag skulle rekommendera en dörr-sensor på badrumsdörren också. Det gör att om dörren är stängd och någon rör sig i badrummet kan du anta att någon är i badrummet tills dörren öppnas igen (även om någon skulle sitta still en längre tid...)
jang
Medlem
Posts: 388
Joined: 05 Jan 2014, 00:44
10
Location: Stockholm

Det här är en ganska vanligt scenario men det blir lätt komplext pga av alla villkor. Om man missar något fall så är det lätt hänt att någon blir kvar i ett mörkt badrum.
Detsamma gäller för många hemlarm scener med många olika events som förändrar det tillstånd som larmet ska befinna sig i...
Vad som brukar vara bra är att man definierar alla "tillstånd" som scenen (badrummet i det här fallet) kan vara i, och alla händelser som gör att badrummet flyttar sig från ett tillstånd till ett annat. Och sedan vara säker på att man täcker alla kombinationer. Om man utesluter någon kombination så ska man vara 101% säker att det aldrig kan hända (och även då bör man lägga in ett felmeddelande).
I det här fallet kan badrummet vara i 3 tillstånd; 'empty', 'entered', dvs någon är i badrummet men inte i duschen, eller 'showering', någon är i duschen.
Jag brukar koda sådana här scener som tillståndsmaskiner i mitt framework EventRunner, och då ser det ut såhär. Det går i princip att göra i "vanliga" scener också med lite mera pill...

Code: Select all

function FROM(state) return bathroom_mode==state end
function STATE(state) return bathroom_mode==state end
function TO(state) bathroom_mode=state end
bathroom_mode = 'empty'-- starting state

motionEntrance = 88
motionShower   = 89
luxSensor      = 92
dimmerRoof     = 90
switchMirror   = 91

-------------- EVENTS -----------------

rule("{motionEntrance}:breached => post(#motionEntrance)")
rule("{motionShower}:breached => post(#motionShower)")
rule("for(00:10,{motionEntrance, motionShower}:safe) & 05:30..22:59:59 => post(#safe)") -- Safe at day
rule("for(00:03,{motionEntrance, motionShower}:safe) & 23:00..05:29:59 => post(#safe)") -- Safe at night

-------------- STATE MACHINE -----------------
rule([[#motionEntrance => 
  || FROM('empty') >> TO('entered'); log('Someone entered'); post(#turnOnLights) 
  || FROM('entered') >> TO('entered');  log('Someone entered, already knew that') 
  || FROM('showering') >> TO('showering');  log('Someone entered, already showering')
  ]])
  
rule([[#motionShower => 
  || FROM('empty') >> TO('showering'); log('Someone showering (and I missed entrance)');  post(#turnOnLights)
  || FROM('entered') >> TO('showering');  log('Moved from entering to showering')
  || FROM('showering') >> TO('showering');  log('Someone showering, already knew that')
  ]])

rule([[#safe => 
  || FROM('empty') >> TO('empty'); log('Safe and empty, already knew that')
  || FROM('entered') >> TO('empty');  log('Safe, someone left entrance'); post(#turnOffLights)
  || FROM('showering') >> TO('empty');  log('Safe, and someone last showered'); post(#turnOffLights)
  ]])

------------- ACTIONS ---------------
rule([[#turnOnLights => 
  || 23:00..05:30 & STATE('showering')                        >> dimmerRoof:isOff & dimmerRoof:value=100
  || 05:30..23:00 & STATE('showering') & luxSensor:lux < 100  >> switchMirror:isOff & switchMirror:on; dimmerRoof:isOff & dimmerRoof:value=100
  || 05:30..23:00 & STATE('showering') & luxSensor:lux >= 100 >> switchMirror:isOff & switchMirror:on; dimmerRoof:isOff & dimmerRoof:value=100
  || 23:00..05:30                                             >> dimmerRoof:isOff & dimmerRoof:value=10
  || 05:30..23:00 & luxSensor:lux < 100                       >> switchMirror:isOff & switchMirror:on; dimmerRoof:isOff & dimmerRoof:value=100
  || 05:30..23:00 & luxSensor:lux >= 100                      >> switchMirror:isOff & switchMirror:on
  ]])
  
rule([[#turnOffLights => 
  || 23:00..05:30 >> {dimmerRoof, switchMirror}:off
  || 05:30..23:00 >> {dimmerRoof, switchMirror}:off
  ]])
  
  ---- Test rules by setting off sensors...
  rule("luxSensor:value=200")
  rule("wait(00:10:00); motionEntrance:on") -- enter bathroom
  rule("wait(00:11:00); motionShower:on") -- enter Shower
  rule("wait(00:11:30); motionEntrance:off") -- motionEntrance is safe
  rule("wait(00:14:30); motionEntrance:on")  -- exit shower, breach entrance
  rule("wait(00:14:50); motionShower:off")  -- motionShower is safe
  rule("wait(00:17:00); motionEntrance:off") -- exit bathroom
  
Det kanske ser lite överambitiöst ut men det är så lätt att missa någon möjlig kombination av tillstånd och händelse. Dessutom när man börjar strukturera upp sin scen på det här sättet så börjar man få en bättre förståelse/specifikation av scenen är när man försöker förklara den muntligt. Dvs. man upptäcker tillstånd och händelser som man inte tänkt på. Det finns naturligtvis många olika sätt att dela upp den här scenen i tillstånd och händelser men det här är en variant.
Ex. upptäckte jag att med den modell jag provade så man kan lämna duschen och badrummet utan att hamna i tillstånd "entrance", beroende på hur man trigger rörelsesensorerna med det här sättet att definera tillståndsövergångarna, med för och nackdelar. Det går att ändra mha andra händelsedefinitioner och övergångar.
Det är också ganska lätt att introducera en dörr-sensor som extra händelse och som förhindrar att vi släcker när någon rört sig i badrummet med dörren stängd.

En annan fördel är att jag kan posta "simulerade" triggers för rörelsesensorerna för att testa logiken i scenen.

Code: Select all

Wed/Apr/24,16:46:24:[20:1] Loading rules
Wed/Apr/24,16:46:24:[20:1] Rule:1:{motionEntrance}:breached => post(#motionEntrance)
Wed/Apr/24,16:46:24:[20:1] Rule:2:{motionShower}:breached => post(#motionShower)
Wed/Apr/24,16:46:24:[20:1] Rule:3:for(00:10,{motionEntrance, motionShower}:safe) & 05:30..22:59:59 => post(#safe)
Wed/Apr/24,16:46:24:[20:1] Rule:4:for(00:03,{motionEntrance, motionShower}:safe) & 23:00..05:29:59 => post(#safe)
Wed/Apr/24,16:46:24:[20:1] Rule:5:#motionEntrance => 
Wed/Apr/24,16:46:24:[20:1] Rule:6:#motionShower => 
Wed/Apr/24,16:46:24:[20:1] Rule:7:#safe => 
Wed/Apr/24,16:46:24:[20:1] Rule:8:#turnOnLights => 
Wed/Apr/24,16:46:24:[20:1] Rule:9:#turnOffLights => 
Wed/Apr/24,16:46:24:[20:1] fibaro:call(92,"turnOn")
Wed/Apr/24,16:46:24:[20:1] fibaro:call(92,"setValue",200)
Wed/Apr/24,16:46:24:[20:1] 
Wed/Apr/24,16:46:24:[20:1] Scene running
Wed/Apr/24,16:56:24:[20:1] fibaro:call(88,"turnOn")
Wed/Apr/24,16:56:24:[20:1] Posting {"type":"motionEntrance"} at Wed Apr 24 16:56:24
Wed/Apr/24,16:56:24:[20:1] Someone entered
Wed/Apr/24,16:56:24:[20:1] Posting {"type":"turnOnLights"} at Wed Apr 24 16:56:24
Wed/Apr/24,16:56:24:[20:1] fibaro:call(91,"turnOn")
Wed/Apr/24,16:57:24:[20:1] fibaro:call(89,"turnOn")
Wed/Apr/24,16:57:24:[20:1] Posting {"type":"motionShower"} at Wed Apr 24 16:57:24
Wed/Apr/24,16:57:24:[20:1] Moved from entering to showering
Wed/Apr/24,16:57:54:[20:1] fibaro:call(88,"turnOff")
Wed/Apr/24,17:00:54:[20:1] fibaro:call(88,"turnOn")
Wed/Apr/24,17:00:54:[20:1] Posting {"type":"motionEntrance"} at Wed Apr 24 17:00:54
Wed/Apr/24,17:00:54:[20:1] Someone entered, already showering
Wed/Apr/24,17:01:14:[20:1] fibaro:call(89,"turnOff")
Wed/Apr/24,17:03:24:[20:1] fibaro:call(88,"turnOff")
Wed/Apr/24,17:13:24:[20:1] Posting {"type":"safe"} at Wed Apr 24 17:13:24
Wed/Apr/24,17:13:24:[20:1] Safe, and someone last showered
Wed/Apr/24,17:13:24:[20:1] Posting {"type":"turnOffLights"} at Wed Apr 24 17:13:24
Wed/Apr/24,17:13:24:[20:1] fibaro:call(90,"turnOff")
Wed/Apr/24,17:13:24:[20:1] fibaro:call(91,"turnOff")
Wed/Apr/24,23:03:00:[20:1] Posting {"type":"safe"} at Wed Apr 24 23:03:00
Wed/Apr/24,23:03:00:[20:1] Safe and empty, already knew that
Nå, det är ingen färdig lösning för dig men kanske lite inspiration.
User avatar
Texan
Medlem
Posts: 169
Joined: 25 Dec 2015, 15:07
8

Mitt kunnande i kodning är minimal :oops:
men jag får detta - misstänker att man måste lägga till "varibelpanel"....?

[DEBUG] 21:01:32: 2019-04-24 21:01:32.062794 [ fatal] Unknown exception: /opt/fibaro/scenes/200.lua:14: attempt to call global 'rule' (a nil value)
jang
Medlem
Posts: 388
Joined: 05 Jan 2014, 00:44
10
Location: Stockholm

Ja, det använder mitt framework EventRunner som beskrivs här
viewtopic.php?f=38&t=6878
... så det saknas en hel del kod för att det ska fungera.

Min tanke med posten var mest att illustrera hur man kan tänka för att konstruera sådana här scener - och hur mycket svårare det är i praktiken att specificera lite mera komplexa scener av den här typen.
Om dina programmeringskunskaper är minimala så kan det vara lite jobbigt att komma igång med EventRunner (bortsett från Lua och programmering så måste man sätta sig in i mitt eget påhittade språk EventScript), så jag är inte säker att jag skulle rekommendera det som första steg.
Det finns en hel del färdiga "badrumsscener" på fibaro forumet men de har oftast kodats för ett specifikt fall och om man börjar addera extra villkor som du har så blir det snabbt komplicerat. Det gäller för alla "smart and very smart lightning scenes" också.

Jag inkluderar bathroom.lua som är den kompletta filen som kan köra på en HC2 och som jag testade i min emulator. Du måste ändra ID på enheterna så att de passar dig. Jag kan inte garantera att scenen löser ditt problem och det kan behövas en del anpassningar. Fördel också om man sätter upp utveckling på en PC (i länken ovan) så att man kan testa scenen först.
Attachments
Badthroom.lua.zip
(31.35 KiB) Downloaded 360 times
maxxar
Medlem
Posts: 126
Joined: 06 Sep 2012, 13:30
11

Såg din ER badrumsscen och tyckte den verkade intressant, kör ju "Very smart lights" scener i bland annat badrummen.
Men har testat ditt förslag med ER som du visat i denna tråden, har ungefär samma upplägg.
En rörelsesensor i badrum och en i dusch samt onoff brytare i tak och över spegel.
Men tänkte sätta en sensor på dörren oxå för att lösa ut "långsittare"
Har inte lyckats riktigt med det, utan kör med följande kod just nu.
Tips mottages tacksamt

Kan du även förklara delen med Test rules


Har lagt allt i en egen ER scen för test, och tanken är att lägga in fler liknande scener i samma.

Code: Select all

function main()
  local rule,define = Rule.eval, Util.defvar

  HT =
  {
    dev = 
    { badrum = {tak = 106, rorelse = 1241, duschrorelse = 115, luxsensor = 117, spegel = 108 },
    },
    other = "other"
  }

  --or read in "HomeTable"
  --local HT = type(_homeTable)=='number' and api.get("/scenes/".._homeTable).lua or fibaro:getGlobalValue(_homeTable) 
  --HT = json.decode(HT)
  Util.defvars(HT.dev)            -- Make HomeTable defs available in EventScript
  Util.reverseMapDef(HT.dev)      -- Make HomeTable names available for logger

  if _EMULATED then _System.speed(true) end
  
  --[[
  Har följande;
2 fibaro rörelsesensorer, en vid ingången till badrummet och en vid duschen.
1 fibaro switch som styr tak (spotlights)
1 fibaro switch som styr lampor vid spegel

Jag tar ingen hänsyn till lux utan sensorn som sitter vid ingången tänkte jag skulle tända lamporna vid spegeln och tak i minst 3min när man kommer in i badrummet eller så lnge det är rörelse, och sensorn vid duschen ska hålla lamporna tända så länge man duschar.
Sedan ifall man går upp på natten exempelvis mellan 23:30 och 5:30 och huset är i läge Sover så skall endast spegeln tändas upp.
Och på natten kan det släckas efter 2 min inaktivitet.
  --]]
  
function FROM(state) return bathroom_mode==state end
function STATE(state) return bathroom_mode==state end
function TO(state) bathroom_mode=state end
bathroom_mode = 'empty'-- starting state

motionEntrance = 1241
motionShower   = 115
dimmerRoof     = 106
switchMirror   = 108

-------------- EVENTS -----------------

  
rule("{badrum.rorelse}:breached => post(#motionEntrance)")
rule("{badrum.duschrorelse}:breached => post(#motionShower)")
rule("for(00:03,{badrum.rorelse, badrum.duschrorelse}:safe) & 05:30..22:59:59 => post(#safe)") -- Safe at day
rule("for(00:02,{badrum.rorelse, badrum.duschrorelse}:safe) & 23:00..05:29:59 => post(#safe)") -- Safe at night

-------------- STATE MACHINE -----------------
rule([[#motionEntrance => 
  || FROM('empty') >> TO('entered'); log('Someone entered'); post(#turnOnLights) 
  || FROM('entered') >> TO('entered');  log('Someone entered, already knew that') 
  || FROM('showering') >> TO('showering');  log('Someone entered, already showering')
  ]])
  
rule([[#motionShower => 
  || FROM('empty') >> TO('showering'); log('Someone showering (and I missed entrance)');  post(#turnOnLights)
  || FROM('entered') >> TO('showering');  log('Moved from entering to showering')
  || FROM('showering') >> TO('showering');  log('Someone showering, already knew that')
  ]])

rule([[#safe => 
  || FROM('empty') >> TO('empty'); log('Safe and empty, already knew that')
  || FROM('entered') >> TO('empty');  log('Safe, someone left entrance'); post(#turnOffLights)
  || FROM('showering') >> TO('empty');  log('Safe, and someone last showered'); post(#turnOffLights)
  ]])

------------- ACTIONS ---------------
rule([[#turnOnLights => 
  || 23:00..05:30 & STATE('showering') & $Sovlage=='Vaken'    >> badrum.spegel:isOff & badrum.spegel:on; badrum.tak:isOff & badrum.tak:on 
  || 05:30..23:00 & STATE('showering') & $Sovlage=='Vaken'    >> badrum.spegel:isOff & badrum.spegel:on; badrum.tak:isOff & badrum.tak:on
  || 23:00..05:30 & $Sovlage=='Vaken'    					  >> badrum.spegel:isOff & badrum.spegel:on; badrum.tak:isOff & badrum.tak:on 
  || 05:30..23:00 & $Sovlage=='Vaken'  						  >> badrum.spegel:isOff & badrum.spegel:on; badrum.tak:isOff & badrum.tak:on
  || 23:00..05:30 & STATE('showering') & $Sovlage=='Sover'    >> badrum.spegel:isOff & badrum.spegel:on
  || 05:30..23:00 & STATE('showering') & $Sovlage=='Sover'    >> badrum.spegel:isOff & badrum.spegel:on
  || 23:00..05:30 & $Sovlage=='Sover'    					  >> badrum.spegel:isOff & badrum.spegel:on
  || 05:30..23:00 & $Sovlage=='Sover'  						  >> badrum.spegel:isOff & badrum.spegel:on
  ]])
  
rule([[#turnOffLights => 
  || 23:00..05:30 >> {badrum.tak, badrum.spegel}:off
  || 05:30..23:00 >> {badrum.tak, badrum.spegel}:off
  ]])
  
  ---- Test rules by setting off sensors...
  rule("wait(00:10:00); badrum.rorelse:on") -- enter bathroom
  rule("wait(00:11:00); badrum.duschrorelse:on") -- enter Shower
  rule("wait(00:11:30); badrum.rorelse:off") -- motionEntrance is safe
  rule("wait(00:14:30); badrum.rorelse:off")  -- exit shower, breach entrance
  rule("wait(00:14:50); badrum.duschrorelse:off")  -- motionShower is safe
  rule("wait(00:17:00); badrum.rorelse:off") -- exit bathroom

  --rule("@@00:00:05 => f=!f; || f >> log('Ding!') || true >> log('Dong!')") -- example rule logging ding/dong every 10 second

  --if dofile then dofile("example_rules.lua") end     -- some more example rules to try out...
end -- main()
jang
Medlem
Posts: 388
Joined: 05 Jan 2014, 00:44
10
Location: Stockholm

Hej,
Reglerna ser väl ok ut. Badrummet blir #safe efter 3min om ingen rörelse noteras vilket kan hända om man sitter still...
En sensor på dörren kan hjälpa.

Test rules är regler som egentligen inte är regler (saknar '=>') men är uttryck som evalueras när scriptet startar. I det här fallet så väntar de ett antal minuter och sedan så "triggar" de sensorer genom att slå på dem. Det här funkar bara i HC2 emulatorn som man kör på PC/Mac. Dessutom kan man köra scenen fortare än realtid så man ser direkt vad som händer. I ditt exempel så fejkar vi att sensorerna i badrummet slås på och av i en viss sekvens så att vi ser om våra regler triggar korrekt.
Post Reply