The switch opens the garage door, the feedback is from the Garage door closed contact.
At the moment the switch has a 1 second expiry as it is a momentary switch for the garage door opener.
I want to create an item so it can be reflected in Apple Homekit as at the moment the switch returns to off after the one second, even if the door is open. I want the homekit switch to reflect the status of the Door (from the garagedoorCcontact)
//GARAGE DOOR STATE
rule "Garage door opening"
when
Item GarageDoorCContact changed to OPEN //Door opening
then
GarageDoorCContact1.postUpdate( "OPENING" )
end
rule "Garage door closing"
when
Item GarageDoorOContact changed to CLOSED //Door closing
then
GarageDoorCContact1.postUpdate( "CLOSING" )
end
rule "Garage door closed"
when
Item GarageDoorCContact changed to CLOSED // Door closed
then
GarageDoorCContact1.postUpdate( "CLOSED" )
end
rule "Garage door open"
when
Item GarageDoorOContact changed to OPEN //Door open
then
GarageDoorCContact1.postUpdate( "OPEN" )
end
OK, so Switch controls the opening of the door. A Contact reflects the state of the door. Thatās what you have now. So what do you want? If you are trying to combine the Switch and Contact into one Item than the answer is you canāt.
A Switch can only be ON or OFF. Period. And you have the Switch configured to automatically turn OFF after a second. There is no possible way that you can use this same Switch to represent the OPEN/CLOSE state of the Garage door. I donāt know how MyQ binding does it but it either didnāt use a Switch Item, or it used ON to represent the door is OPEN and OFF to represent that the door is CLOSED. But I donāt see how, even with this configuration, that you can both control the garage door and represent itās state in one Item. Maybe with autoupdate=false, but you are still left with the fact that the Item is a Switch, not a Contact.
Well, almostā¦
The push button is wired to the IHC controller (input module). The IHC controller sends 868mhz signal to a IHC wireless dimmer. I do have IHC wireless push buttons as well. So everything goes through the controller wireless.
I do see youĀ“re points, though IĀ“m still positive this should be possible.
But letĀ“s stick to the rollershutter (garagedoor) first. Then I might have been convinced never to try a dimmer, afterwards
"Software Rollershutter"
I have measured the time it takes to open and close the garagedoor.
22.5 seconds from fully closed to fully open.
19.5 seconds from fully open to fully closed.
I assume all timings should be in done in ms?
In order to ārecordā the direction, is there any good way to do this, or is this by using proxyitems, and hope it never gets out of sync? (or perhaps resync each time the garagdoor reach a sensor, which would be the mostly used way normally (fully open or fully closed).
In one of your previous messages above you wrote
Since it takes 22500ms to fully open, I assume for every 2250ms, it should postUpdate the Rollershutter item at a step of 10%?
What ever makes the math easiest for you. It ultimately doesnāt matter.
See the state machine replies I made showing how to use the events and changes to the contacts to determine what direction the door is going in. In short, Iāve already told you how to do that part on post 13 above. Looking for Ideas on Garage door Solution
Absolutely. Thatās what ārecalibrate the percent to 0 or 100ā that I said multiple times above means.
Plus you have a little bit of calculations to do when the door stops because it will not have traveled for a full 2250ms. So what I would do to make it easy is just take a time stamp at the beginning of motion. Periodically check how long the door has been moving (Iād probably check every 500 msec so itās nice and responsive but you can experiment). Then you subtract the current timestamp in milliseconds from the timestamp taken when the door started moving divided by the total amount of time it takes for the door to open to get the percentage. That eliminates the special case when you stop the door.
var Timer timer = null
var Number start_time = 0
val calcPercent = [ Number start_time |
val OPENTIME = 22500
val CLOSETIME = -19500 // we count up from closed, count down from opened
val delta = now.millis - start_time
return (delta / if(GarageDoor.state == "OPENING") OPENTIME else CLOSETIME).intValue
]
rule "door started moving"
Item GarageDoor changed to OPENING or
Item GarageDoor changed to CLOSING
than
start_time = now.millis
timer = createTimer(now.plusMillis(500), [ |
val percent = calcPercent.apply(start_time)
GarageDoorPercent.postUpdate(GarageDoor.state + percent)
if(GarageDoor.state == "OPENING" || GarageDoor.state == "CLOSING"){
timer.reschedule(now.plusMillis(500))
])
end
rule "door stopped"
Item GarageDoor changed to STOPPED or
Item GarageDoor changed to CLOSED or
Item GarageDoor changed to OPENED
than
timer?.cancel
var newState = 0 // covers the CLOSED case
switch(GarageDoor.state.toString){
case "OPENED": newState = 100
case "STOPPED": newState = calcPercent.apply(start_time)
}
GarageDoorPercent.postUpdate(newState)
end
The above was just typed in. There are almost certainly errors.
I keep looking at that post and I dont get itā¦
First of all, its not Rules DSL. (It still seem quite logic anyway).
Second, the part:
# Door is in motion
elif currState != "STOPPED":
newState = "STOPPED"
# Door is partially open but not moving
else:
newState = "OPENING" if prevState == "CLOSING" else "CLOSING"
is really confusingā¦
currState not equal to āSTOPPEDā. Where did STOPPED come from? I assume its suppose to be a value string like CLOSED and OPENED from the sensors?
And I cant see how the āOPENINGā and āCLOSINGā is beeing defined either.
It seems like the logic is turned upside down, and something is missingā¦ But itĀ“s probably just me who dont get it.
Before we get to that line weāve tested whether the door is OPENED or CLOSED. Itās neither of those so we know that the door is in motion, either opening it closing. The button was pressed to trigger this rule so we know that the door is now stopped and partially open.
When you press the button and the door is in motion, the door becomes stopped.
Stopped indicates the door is not in motion but it is neither fully open not fully closed either.
They after just Strings. You can make them anything you want. The important thing is you come up with names for reach of the states and used those names to represent when the door is in a given state. Iāve used:
āCLOSEDā: door is fully closed
āOPENEDā: door us fully opened
āOPENINGā: door is in motion in the opening direction
āCLOSINGā: door is in motion in the closing direction
āSTOPPEDā: door is not in motion but also not fully open not fully closed.
After a certain time, yes. But this timer isnĀ“t part of the rule? So in this rule, the door never stops, at least not untill it has reach an end (sensor)ā¦ The door should be on the move, until āsomethingā state it has stopped?
Hmmā¦ My problem may be, that I thought this was a finished ruleā¦ But am I right in assuming, this is just a principal, and therefore part of a rule?
So the CLOSED and OPENED isnĀ“t actual states from the sensors?
There is no timer. If the door is closed and you push the button. The door is no longer closed, itās in motion. If you press the button again while itās in motion the door stops moving. Itās not closed yet, itās just stopped.
Itās all event driven.
Or the button is pressed when the door is moving.
Yes, ordering the button again is the something.
The logic is finished. The code is untested and may have bugs.
Look at the state table in part 13. That defined all the behaviors implemented by the rules. It defines all the states that the door can be in, including stopped. And it explains hi the door traditions from one state to another.
If you need to, go study state machines in general.
NONE of these a are states from the sensors. These are the states of our state machine representing the state of the garage door. They are made up strings. You could use āfooā and ābarā for all it matters.
The sensors and the button provide the events that are used to transition from one state to another state. Thatās all.
Hmm simply dont understandā¦ I do get the idea, but I dont see how to rewrite it to a working ruleā¦
I also got another idea for detamin the directionā¦
The sensors IĀ“ve got can be either open or closedā¦ When bottom sensor is closed, the door is closedā¦
Now IĀ“m thinkingā¦ Byt the use of two proxyswicthes, wouldnĀ“t this be suitable for detamin the direction?
when
item bottom.sensor changed from CLOSED to OPEN
then
proxy_opening.postUpdate (OPENING)
And the same for the top sensor:
when
item top.sensor changed from CLOSED to OPEN
then
proxy_closing.postUpdate (CLOSING)
Unless there are syntax errors, b it already is a working rule. Itās complete. It covers all the states. It handled all of the events. What needs rewriting?
Which is exactly what my existing rule above does. It just does it all in one rule.
And your proposal only handles the case where the door fully opens or fully closes every time you press the button. What happens when the door is opening and you press the button? It stops moving. Ovne might say it enters a STOPPED state. What happens when you press the button again? It starts closing. If there is any complexity in that rule itās because it handles this too.
I dont see the actual sensors (and the button). (Or IĀ“m simply steering blindā¦ Need to test it, but first I have to ātranslate itā to dsl rules.
Yeah, I just had a second thought while having dinner and came to exact same conclusionā¦ Thats a bad ideaā¦
The direction has to be detamin from the buttonā¦ And I think it would be best to persist this as well. I suspect mapdb would be suitable for this?
@when("Item DoorOpenedSensor changed") // sensor that is OPENED when door is fully open
@when("Item DoorClosedSensor changed") // sensor that is CLOSED when door is fully closed
...
# Door is fully closed
if items["DoorClosedSensor"] == CLOSED:
newState = "CLOSED"
# Door is fully opened
elif items["DoorOpenedSensor"] == CLOSED:
newState = "OPENED"
Can a var be sat equal to an item in rules dsl ?
I have a few problems getting this translated to rules dslā¦ I think IĀ“m close, but I think there is a few problems setting the variables for currState and the Ā“global prevStateĀ“ at the bottom.
This is how it looks:
rule "Garage door status"
when
Item GaragePortBottomSensor changed or
Item GaragePortTopSensor changed or
Item garage_bryggers_NV changed from OFF to ON
then
var newState = UNDEF
var currState = GarageDoorState
// Garage door fully closed
if(GaragePortBottomSensor.state.toString == "CLOSED" ) {
newState = "CLOSED" }
else
// Garage door fully open
if(GaragePortTopSensor.state.toString == "CLOSED" ) {
newState = "OPEN" }
else
// Door is in motion
if(currState != "STOPPED") {
newState = "STOPPED" }
else
// Door is partially open but not moving
if(prevState == "CLOSING") {
newState = "OPENING" }
else {
newState = "CLOSING" }
// Could use persistence for this, keep track of the previous state so we can handle the STOPPED case
global prevState
prevState = currState
GarageDoorState.postUpdate(newState)
end
// Proxy items
// Switch GarageDoorState
I tried commenting out the global cause it gave an errorā¦
2019-11-27 23:29:59.448 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Garage door status': The name 'global' cannot be resolved to an item or type; line 33, column 9, length 6
Then I get this error when I start the garagedoor:
2019-11-27 23:31:01.592 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Garage door status': An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid: (eProxyURI: garagedoor.rules#|::0.2.0.2.0.3::0::/1)
Yes but there rarely is a point to. You either already know the Item so just use the Item name directly, or you really want something from the Item like itās name or state so you would assign that to a variable.
Note, that items["DoorState"] returns the state of the Item DoorState. It is not the Item DoorState itself. So you need to ser currState to GarageDoorState.state.toString.
prevState is a global variable. In Rules DSL, as youāve seen before, you define a variable as a global by putting the var above the Rules. There is nothing special that you need to do to access it. In Python you need to tell it you are using a global variable. In short global prevState is meaningless in Rules DSL.
You get the error when you try to set prevState is because you never defined prevState. If you look at the Python code, even there prevState is defined before the Rule.
IĀ“m not sure how to do thisā¦ I believe its suppose to be a val and not a var then like this?
val currState = GarageDoorState.state.toString
Second
IĀ“d set the prevState as a val before the ruleā¦ When I saved the rule, I got this issue:
2019-11-28 00:00:54.512 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'garagedoor.rules', using it anyway:
The field Tmp_garagedoorRules.prevState refers to the missing type Object
Assignment to final field
The field Tmp_garagedoorRules.prevState refers to the missing type Object
Right after (without saving) I got this, with no issue:
2019-11-28 00:00:54.910 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'garagedoor.rules'
This is the error I get, when I fire the rule:
2019-11-28 00:05:50.996 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Garage door status': An error occurred during the script execution: Cannot assign a value in null context.