[best practice inquiry] Planning a project to upgrade garage door automation

Tags: #<Tag:0x00007f1737f20238> #<Tag:0x00007f1737f20030> #<Tag:0x00007f174181ff88>

Hello community,

I recently have more time to get back into home automation and would like to upgrade my existing garage door solution.

Requirements

  • Three plainly switch- and proprietary RF-controlled, automatic garage doors shall be integrated into our OpenHAB2-system.
  • The resulting software shall feature a TCP/IP-interface (e.g. REST) in order to control the relays and retrieve the states from android/apple devices (car radio, mobiles, …) outside of the LAN (DynDNS is up and running).
  • The hardware to achieve this must be compatible with ESP8266 (EasyESP) or RaspberryPi.
  • The doors shall shut automatically after a configured period of time to compensate for human error (forgot to close garage door).

Old solution

  • Custom-made django-based HTTP-Service running on RaspberryPi Zero controlling one general-purpose relay (GPIO) to deliver a 1 sec pulse (mimicking the manual switches) to trigger open/close and one simple magnetic door contact sensor to detect whether the door is shut (1).
  • Since all these garage doors need 14 sec to completely open/shut, this delta was used to ensure the doors are not stuck or obstructed (trigger -> wait 14s ? sensor is still 0 -> trigger… up to 3 times, since it is uncertain whether the door is opening or closing after a trigger) (important). In case the shutting operation stays unsuccessful, an alert is raised.
  • Works very well and efficiently, but not very satisfying in light of OpenHAB2 usage for the rest of our home automation.

New approach

  • An ESP8266 with an additional ultrasound distance sensor measures the distance of the upper end of the door from the motor unit on it’s mechanical rail with an interval of 1 sec (prototype assembled, tested and installed) in order to determine the position and open/close direction of the door.
  • Prototype XTend-implementations for OH2 are already implemented, but due to frequent outliers in the ultrasonic measurements, this solution would require a statistical approach to increase certainty (the rounded mode of cm over say 3-5 sec seems most suited).

Questions to the community

  1. I did not manage in XTend, so what is the right approach (best practice) to achieve this?
  2. Do I implement it as a new add-on (would be a first for me, although I have tons of professional OOP- and Java-experience and IntelliJ is already set up to start right away)?
  3. I need better code inspection and completion, because the last time it was too much trial & error debugging. I used VSCode with OH-Plugin to script the XTend. It was awful to try and include native Java-libraries to achieve this. Is there anything that I missed?
  4. How would you guys proceed?

I would love your insight and experience to guide me here, so that I won’t invent the wheel anew and waste hours for something so straight-forward.

Cheers,

Seb

There are other rule languages for OH2, but I can’t imagine you’ll be served any better than VSCode.
Just because of history, the majority of examples are in DSL (“Xtend”).

Node-red is used by some, you might fare better there.

What you intend to do is quite intricate - but so far as I can see the building blocks boils down to simple maths like averaging, some timing, and if-this-do-that logic. What did you need to import libraries for?

Hi rossko57,

thank you for the reply.

Alright, if you can answer me to how to get the mode of a sample of 5 values over 5 sec from 5 different MQTT msgs with the standard OH-API the easy way, I would be very grateful.

Cheers,

Seb

For the rules side of things, Python checks all of your boxes. You can use the Helper Libraries to make writing rules similar to Xtend. To add autocompletion for the Helper Libraries and openHAB itself you cna use my Python stubs, while there is no version available for OH2 at this time I am hoping to have the time this weekend to generate them.

Cheers Ivan,

that should open up a ton of new possibilities for me. Thank you very much!

BTW: Is it a good idea to upgrade to OH3 at this point?

Best,

Seb

1 Like

Nope. But I don’t think I’d do that, it’s a door opener not a self-driving car.

Maybe it’s mechanism noise affecting the reading, but whatever, you have what you have.
A simple filter on delta can eliminate the most ridiculous outliers as the data comes in - you know it can’t have moved that far in one step. Then just a running average over the last few steps, depending how fast it does move.
Something more sophisticated might estimate the trend.

Really, this should be done at the other end though. I wouldn’t have thought you’d be wanting to pour continuous sensor readings about door position over the network 24hrs a day for processing. Ideally, sensor just tells us about changes.

Hi again,

well, the ESP8266-OS can only measure once per second and I would like pretty frequent updates. That means an average is not useful when I aim for 0.2 Hz frequency. Therefore I have to use the mode or the median. The latter is probably even better to eliminate outliers in that small sample.

But thanks for the replies, mate. I appreciate it.

Cheers,

Seb

Okay. Is that going to be granular enough for a total 14 sec travel time, if you’re using values from 3 or 4 secs ago? Presumably this is just to detect a stalled door, or end of travel?

  1. I don’t know that there is a best practice over all. But there are things you can do. For example, if the delta from a sensor reading is too large, throw it out and ignore it in the rule. That’s easy to do in Rules DSL with a simple if statement. Nothing in the above really sounds all that complicated really. If you need to go to a statistical approach you might use Persistence and use averageSince or the like to perform that stuff, but that’s best done on the microcontroller really (see below).

  2. No need for that. It can easily be handled in rules using almost any one of the supported rules languages.

  3. If you know how to program already, Rules DSL is very painful to use. You’ll want to use one of the other supported languages. Python was the most popular. JavaScript is growing in popularity. There is a Ruby add-on for OH 3 in work. And of course Groovy is also supported. But these are not going to eliminate the need to import and use Java stuff. All the interaction between openHAB and the rules is through Java Objects. And you can’t really easily include extra Java libraries in your rules anyway (I know some people have figured out how to do it but it’s really hard to get working). You’d either just do it in Rules DSL or use what openHAB and the Java language provides. Python has a way to install third party Python libraries. In some cases you can use third party JavaScript libraries too. But in both cases there are limitation.

But for this you don’t really need anything special. It’s really pretty simple really.

However, none of these rules rules is going to give you the sort of intellisence and code completion you are used to when doing Java programming in IntelliJ. The languages and the environment simply do not support that.

  1. I would add in one or two more reed sensors on the door to give additional information about the fully opened/closed status of the door. Then I’d only use the sonic sensor for “door is in motion”, direction, and perhaps % open readings.

The timing stuff seems pretty straight forward. When the door is triggered, start a timer for a certain number of seconds (maybe 2 or 3). On each new door sensor reading reschedule the timer. When the door has stopped moving for the 2-3 seconds check to see if the door is fully opened/closed. If not take remedial actions as you described above or alert or the like. If it is fully open or closed the trigger was a success and end.

var Timer garageTimer = null

rule "Garage Opening"
when
    Item SonicSensor changed // lets assume that it's being filtered as described below
then
    if(garageTimer != null) {
        garageTimer.reschedule(now.plusSeconds(2)) // pick a reasonable value
    }
    else {
        garageTimer = createTimer(now.plusSeconds(2), [ |
            if(GarageOpen.state != CLOSED || GarageClosed.state != CLOSED){
                // door stopped moving but isn't fully open or closed, take remedial action here
            }
            // door fully opened or fully closed
            garageTimer = null
        ])
    }
end

Notice that you don’t actually care what the sonic sensor is reporting, just that it’s changing by enough to indicate motion. I’d handle calculating direction and percentage opened in another rule, or even better on the microcontroller itself. And you can see that by:

  • filtering out the obviously erroneous readings
  • a running average or a simple delta between readings since we’ve filtered most of the bad readings out at the source.

If I were implementing this (and in the not too distant future I will be implementing this) I’d filter the erroneous readings at the source. Keep track of the last few readings and only report when the changes are big enough to indicate a “real” change and not the noise. If the delta of a new reading is too large to be reasonable, throw it out at the source.

If that can’t be done at the source, create a proxy Item to represent the reading and add a rule to process the readings, smoothing them out with what ever approach seems reasonable. And to smooth it out I still don’t see why a running average won’t work. Either the events are coming in fast enough to make any statistical approach work (including a running average) or it’s not going to work with any of the statistical approaches anyway.

I really don’t understand this statement at all. What I’m reading is the EPS8266 can only report readings from the sonic sensor once per second. If that’s the case how do you prose to get to 0.2 HZ? OH isn’t going to solve a hardware limitation.

And let’s say you do get to 0.2 HZ somehow (inventing readings out of thin air?), OH isn’t going to be able to handle that. OH is not a real time system. I can’t process events that fast, does a ton of stuff in parallel and therefore cannot even guarantee that the events are processed in order. In fact, on OH 2 you’ll probably have several of these events being processed by the same rule in parallel and if you have more than five such rules processing at the same time, no other rules can run.

So my advice would be if the hardware cannot handle faster updates than once per second, you need to consider different hardware (or perhaps different firmware as I’m pretty sure the ESP8266 can handle a faster refresh rate than that, though perhaps the sonic sensor cannot in which case you can’t get there from here). Then you need to handle the smoothing on the microcontroller, not in openHAB. openHAB will never be able to keep up. Don’t just rely on the sonic sensor. Add a couple of reed sensors and then perhaps the noisiness in the sonic sensor doesn’t matter any more.
Finally, don’t try to do it all in one rule (no matter what language you end up using).

I would recommend to anyone asking that they upgrade to OH3, yes.

And just to clear something up here, 1Hz > 0.2Hz…

1Hz is once a second, 0.2Hz is once every 5 seconds, 5 times a second would be 5Hz.

Doh! I knew that. Don’t know what I was thinking.

So ignore all the stuff I posted about speed and OH keeping up. Though I still agree with rossko57 that the microcontroller should be responsible for filtering the readings, not openHAB. But if one were to implement it on openHAB than, given how infrequently it reports, I’d use a delta from the last “accepted” reading as the way to ignore the erroneous readings. Anything else, average, mode, median, is going to be too far behind to really be useful. It’ll be a few seconds before OH even knows that the door is moving using those approaches.

Of course, with the additional sensors and the approach I describe above, the bad sensor readings may just not matter at all, which would be the best of all worlds.