Waste Collection Belgium [3.3.0;3.4.9)

recycelapp

A rule created by this rule template will query the recycleapp.be website once per day for the waste collection calendar on a specific address in Belgium. It will then update a number of items by fraction for the next collection date of that specific fraction.

The rule template combines well with the Garbage Collection UI widget by @DrRSatzteil.

Language: javascript (ECMAScript 5.1 Nashorn)

A version for OH 4.0 for the JavaScript Scripting Add-on (ECMAScript 2022+ ES6) is available here.

Configuration

The rule has a number of parameters:

  • Time: time of day to trigger the rule, defaults to midnight
  • Street: street name for collection
  • Street number: street number for collection
  • Zip code: zip code for collection
  • Days: number of days to look ahead, optional parameter, default 60

The rule will update one or more DateTime items with the next collection date for the specific fraction. These items are optional. You only need to create items for, and configure the ones, you are interested in.

  • Residual Waste Item
  • PMD Item
  • GFT Item
  • Paper and Cardboard Item
  • Textile Item
  • Pruning Wood Item
  • Glass Item
  • Bulky Waste Item

Note that the above 8 fractions are the ones configured in the rule. The collection of fractions may vary by region. E.g. pruning wood would return the deadline for a pruning woord collection appointment in some places. Not all fractions are collected in all regions.
Also, the strings used in the API response to describe certain (the same) fractions vary by region. Therefore, if one of your fractions is not recognized, it may require adding alternative detection strings to the rule. If you notice this, let me know and the template rule will be completed.
If you have other fractions, you can manually add them to the created rule. If you communicate back, the template will be adjusted.

The rule template will by default log success and failure. The logging level can be increased to DEBUG or TRACE for more detailed information. Use following command in the openHAB console for DEBUG level:
log:set DEBUG org.openhab.model.script.mherwege.wasteBelgium

Suggestions

For a nice representation of the next waste collection, combine this rule template with the Garbage Collection UI widget by @DrRSatzteil.

If you use sitemaps, you can easily render a line in the UI when the collection is in the next days. Here is an example of such a configuration:

		Text item=ResidualWaste label="Residual waste [%1$tA]" icon="error" visibility=[ResidualWaste > -172800]
		Text item=PMD label="PMD [%1$tA]" icon="error" visibility=[PMD > -172800]
		Text item=Paper label="Paper and cardboard [%1$tA]" icon="error" visibility=[Paper > -172800]

A line will only render for a collection within the next 48 hours.

Changelog

This rule template is heavily inspired by the work of @BeanzBE, who developed a binding for the same purpose, not currently part of the openHAB distribution. Many thanks for that. Rather than using the binding as a dependency, I opted to do the required http GET calls directly from the rule.

Version 1.11

  • Update secret key

Version 1.10

  • Added “kerstboom” matching

Version 1.9

  • Added “snoeihout” and “grofvuil” matching

Version 1.8

  • Added “restafval” matching
  • Fixed ZonedDateTime.now() call

Version 1.7

  • Added “omb” and “organiques” for French language matching

Version 1.6

  • Updated api url

Version 1.5

  • Updated access token

Version 1.4

  • Fix glass fraction quotes

Version 1.3

  • Add glass fraction
  • Improved match strings for Herenthout

Version 1.2

  • Make rule work for streetnames with spaces

Version 1.1

  • Fix exception day collections

Version 1.0

  • implemented retry functionality when http request fails

Version 0.4

  • changed capitalization of header field, should not matter but seems to make a difference in stability

Version 0.3

  • added bulky waste
  • add alternative GFT detection string

Version 0.2

  • filtered non collection events
  • captured different collection name for residual waste (huisvuil)

Version 0.1

  • initial release

Resources

See the original forum discussion with reference to the work of @BeanzBE.

https://raw.githubusercontent.com/mherwege/openhab-rule-templates/main/wasteBelgium/wasteBelgium.yaml

2 Likes

after trying the script i get Script execution of rule with UID 'waste_collection' failed: TypeError: Cannot read property "en" from undefined in <eval> at line number 77

Can you send me a direct message with your address, so I can check the api response for you? It looks like the name is missing in the response for some reason.

@stamate_viorel The issue should be solved. Remove and reinstall the template.

Hi,

I have tried the version from 09 May and I get the following error:

2022-05-09 23:02:37.556 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'WasteCollectionMerellaan' failed: TypeError: Cannot get property "accessToken" of null in <eval> at line number 40

@DarkoG This seems to point at a connection issue. There was no response from the website. Can you try going to the website recycleapp.be directly?

Hi @Mherwege

The website is accessible from my LAN and I have checked the internet access from the raspberry Pi running the OH

Could you send me a private message with your address? I will check out. But give me a few days.
It already fails in the first call, so that surprises me.

What is strange, I noticed that I get dates for some types of garbage but it fails on the GFT, which is collected on Fridays and that thing has no value. I double checked the item name used in the role and that looks good.
I will send you PM with my address.

  gft: WasteNextGFTCollection
  pmd: WasteNextPMDCollection
  pruningWood: WasteNextPrunningCollection
  textile: WasteNextTextileCollection

@DarkoG I think it should work now. Strangely enough, gft is called differently in the API response in different places in Belgium. I did not anticipate that, so the rule may need to be extended if used in various places. But I will only know when someone tries.
I see you got over the initial connection issue. Any idea what the problem was?

I don’t know what happened but it probably succeed to connect once. It was failing after and with the latest version I have other logs.

2022-05-12 23:46:58.668 [INFO ] [openhab.event.RuleUpdatedEvent      ] - Rule 'WasteCollection' has been updated.

2022-05-12 23:47:16.678 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

2022-05-12 23:47:21.996 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to retrieve authorization token

2022-05-12 23:47:22.001 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to validate zip code

2022-05-12 23:47:22.005 [WARN ] [b.model.script.mherwege.wasteBelgium] - unable to validate street name

@DarkoG In the latest version, the error you saw before was properly catched, and resulted in the “Unable to retrieve authorization token”. If that fails, all the rest will fail as well. There is something going on with the stability of that internet connection or the load on your RPi. The token request http call times out. Because of your problem, I increased the timeout from 2 seconds to 5 seconds, but it looks like it still fails. I tried your address on my OH installation, and it works fine. I am at a loss now.
Once the data is retrieved once, it should be fairly forgiving for http failures. The data gets updated once a day, but will keep the previous data if it can’t update, which is fine in most cases.
You can manually try to run the rule to see if it succeeds at some point.

@DarkoG You could try the following command on the command line of your RPi:

curl https://recycleapp.be/api/app/v1/access-token -H "x-consumer: recycleapp.be" -H "X-secret: Crgja3EGWe8jdapyr4EEoMBgZACYYjRRcRpaMQrLDW9HJBvmgkfGQyYqLgeXPavAGvnJqkV87PBB2b8zx43q46sUgzqio4yRZbABhtKeagkVKypTEDjKfPgGycjLyJTtLHYpzwJgp4YmmCuJZN9ZmJY8CGEoFs8MKfdJpU9RjkEVfngmmk2LYD4QzFegLNKUbcCeAdEW"

This is the exact command that is used in the rule to retrieve the token. And that one doesn’t return anything in the rule in your case. It always succeeds on my RPi. If this also fails from the command line, the issue is definitely with the internet connection.
It should return a JSON string with 2 fields: expiresAt and accessToken.

@DarkoG I may be on to something. I noticed the rule code uses a header field, x-secret, while the curl uses X-secret. Header field names are normally case insensitive (and should be according to HTTP standards). But it does seem to make a difference in the response. I got a few unauthorized responses when using lower case. I therefore changed the rule slightly.

Hi @Mherwege thanks for the support.

This returns the JSON fields, see below.

I tried pinging google.com while running the rule, and while no ping packets were missed, I get the same error

2022-05-13 21:50:37.654 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to retrieve authorization token

2022-05-13 21:50:37.657 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to validate zip code

2022-05-13 21:50:37.661 [WARN ] [b.model.script.mherwege.wasteBelgium] - unable to validate street name
openhabian@openHABianDevice:~ $ curl https://recycleapp.be/api/app/v1/access-token -H "x-consumer: recycleapp.be" -H "X-secret: Crgja3EGWe8jdapyr4EEoMBgZACYYjRRcRpaMQrLDW9HJBvmgkfGQyYqLgeXPavAGvnJqkV87PBB2b8zx43q46sUgzqio4yRZbABhtKeagkVKypTEDjKfPgGycjLyJTtLHYpzwJgp4YmmCuJZN9ZmJY8CGEoFs8MKfdJpU9RjkEVfngmmk2LYD4QzFegLNKUbcCeAdEW"
{"expiresAt":"2022-05-13T20:48:10.230Z","accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2NTI0NzEzNTAsImV4cCI6MTY1MjQ3NDk1MCwiYXVkIjoicmVjeWNsZWFwcC5iZSJ9.ZV6UL1jo-_sh0TpFuLtXAspmxokz4j2A3PUaOgWoLb4"}openhabian@openHAopenhabian@openHABianDevice:~ $ ping google.com                              PING google.com (142.251.39.110) 56(84) bytes of data.                       64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=1 ttl=57 time=21.0 ms                                                                  64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=2 ttl=57 time=19.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=3 ttl=57 time=15.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=4 ttl=57 time=12.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=5 ttl=57 time=17.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=6 ttl=57 time=14.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=7 ttl=57 time=14.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=8 ttl=57 time=16.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=9 ttl=57 time=16.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=10 ttl=57 time=17.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=11 ttl=57 time=19.2 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=12 ttl=57 time=16.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=13 ttl=57 time=15.0 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=14 ttl=57 time=14.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=15 ttl=57 time=23.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=16 ttl=57 time=13.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=17 ttl=57 time=12.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=18 ttl=57 time=17.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=19 ttl=57 time=19.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=20 ttl=57 time=19.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=21 ttl=57 time=15.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=22 ttl=57 time=14.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=23 ttl=57 time=16.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=24 ttl=57 time=14.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=25 ttl=57 time=13.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=26 ttl=57 time=16.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=27 ttl=57 time=19.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=28 ttl=57 time=14.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=29 ttl=57 time=16.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=30 ttl=57 time=21.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=31 ttl=57 time=15.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=32 ttl=57 time=17.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=33 ttl=57 time=20.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=34 ttl=57 time=15.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=35 ttl=57 time=17.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=36 ttl=57 time=16.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=37 ttl=57 time=15.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=38 ttl=57 time=15.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=39 ttl=57 time=14.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=40 ttl=57 time=17.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=41 ttl=57 time=14.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=42 ttl=57 time=14.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=43 ttl=57 time=13.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=44 ttl=57 time=14.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=45 ttl=57 time=19.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=46 ttl=57 time=14.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=47 ttl=57 time=15.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=48 ttl=57 time=15.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=49 ttl=57 time=15.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=50 ttl=57 time=15.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=51 ttl=57 time=17.0 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=52 ttl=57 time=15.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=53 ttl=57 time=12.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=54 ttl=57 time=12.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=55 ttl=57 time=17.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=56 ttl=57 time=16.0 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=57 ttl=57 time=17.2 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=58 ttl=57 time=15.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=59 ttl=57 time=13.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=60 ttl=57 time=17.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=61 ttl=57 time=16.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=62 ttl=57 time=14.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=63 ttl=57 time=20.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=64 ttl=57 time=24.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=65 ttl=57 time=29.8 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=66 ttl=57 time=18.0 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=67 ttl=57 time=19.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=68 ttl=57 time=17.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=69 ttl=57 time=15.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=70 ttl=57 time=15.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=71 ttl=57 time=23.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=72 ttl=57 time=14.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=73 ttl=57 time=12.9 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=74 ttl=57 time=15.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=75 ttl=57 time=16.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=76 ttl=57 time=13.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=77 ttl=57 time=14.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=78 ttl=57 time=14.5 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=79 ttl=57 time=22.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=80 ttl=57 time=11.4 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=81 ttl=57 time=15.7 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=82 ttl=57 time=17.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=83 ttl=57 time=16.2 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=84 ttl=57 time=15.2 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=85 ttl=57 time=18.1 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=86 ttl=57 time=19.3 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=87 ttl=57 time=15.0 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=88 ttl=57 time=16.6 ms
64 bytes from ams15s48-in-f14.1e100.net (142.251.39.110): icmp_seq=89 ttl=57 time=16.8 ms
^C
--- google.com ping statistics ---
89 packets transmitted, 89 received, 0% packet loss, time 264ms
rtt min/avg/max/mdev = 11.437/16.571/29.753/2.910 ms
openhabian@openHABianDevice:~ $

Update, I changed back to x-consumer and the rule failed on the first run but it succeeded on the following few.
I don’t get it.
Can it be somthing OH related?

@DarkoG It must be OH related, but can’t put my finger on it. The http action I use has been around for a log time. And I couldn’t find anything similar reported so far.
I now also had the problem appear a few times. there was an HTTP timeout error in my logs just before in each case. I then enhanced my rule with timer logic to retry up to 10 times with lengthening intervals. I haven’t seen the retry behaviour kick in so far. This version is not in the template yet, first need to get more comfortable about it working reasonably well.

I am wondering if the http connection in OH is building up something and locking after a while. But I don’t see it yet.

I have new example

2022-05-13 22:37:07.594 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

2022-05-13 22:37:12.607 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to retrieve authorization token

2022-05-13 22:37:12.854 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'WasteCollection' failed: TypeError: Cannot read property "0" from undefined in <eval> at line number 63

2022-05-13 22:37:40.193 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

First attempt failed, 2nd succeeded.

Edit: This behaviour is repeatable, if there is longer pause between 2 rule runs, the first attempt fails:

calendar

2022-05-13 23:33:47.252 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to retrieve authorization token

2022-05-13 23:33:47.521 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'WasteCollection' failed: TypeError: Cannot read property "0" from undefined in <eval> at line number 63

2022-05-13 23:33:51.776 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

2022-05-13 23:37:07.424 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

2022-05-13 23:37:12.433 [WARN ] [b.model.script.mherwege.wasteBelgium] - Unable to retrieve authorization token

2022-05-13 23:37:12.693 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'WasteCollection' failed: TypeError: Cannot read property "0" from undefined in <eval> at line number 63

2022-05-13 23:37:26.876 [INFO ] [b.model.script.mherwege.wasteBelgium] - Retrieving waste calendar

hello i just tested it works but i did get some error likes Darko after updating an item in the script but not saving the rule in the ui. but after a refresh of the browser and running the rule again it updates my items so all good

@DarkoG @stamate_viorel
I have been looking into the http request failure issue and built retry logic into the rule. The rule will now retry getting the info up to 10 times if the connection fails, with increasing intervals.
I believe the reason it sometimes failed has to do with the load on openHAB. But I can’t say for sure what is causing it. I looked at the relevant OH code, but nothing stands out.
I have also experienced the recycleapp website having issues. And with this version of the rule, it did recover. Overall, it will do 10 tries over around 30 min.

Logging should also be better now, especially if you turn on DEBUG logging for org.openhab.model.script.mherwege.wasteBelgium.

I have been running this version of the rule every 5 minutes for a few days now, and it looks like it is behaving correctly without side effects. It was also resilient to connection issues. If you find any issues with it, let me know.