-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Govee water sensors to rtl_433_mqtt_hass #2605
Conversation
Can you explain why the changed code will do the same thing as before for devices other than this sensor? I find this code to tricky to understand by reading it (not being familiar) and think it could do with a comment explaining the point. |
Sure! I wasn't able to make the condition as readable as I would've liked for the reason mentioned in the description. I find a helpful way to think about the new condition is by translating it to english as "if the key from the decoded rtl data is present in the hardcoded mappings and either the Here is the condition for reference:
The idea of matching against the actual value of the key (and not just the name of the key) is what is being added in this pull request. The reason this does not affect the behavior of the preexisting devices is that none of them define a "value" key in their mappings so If you find the condition in the PR description ( In case it helps, here is some sample
In the dictionary above, In principle, this approach would allow other sensors to map to the Happy to add a comment if you'd like! |
6fcb13b
to
770752c
Compare
After spending a little more time thinking about how this code could be made more readable, I came up with the following solution by inverting the conditional and reordering the contents of the main if-else statement:
I've included the logic as it's currently written in the pull request below for comparison:
Let me know if you prefer this version and I will make the change! |
I think I do prefer that, as it puts the normal path first. But the point to me is the reason behind the condition, expressed as a comment in the code -- discussion in PRs does not live on -- not rephrasing code to English, but starrting from the rules about which keys are present and what that means. But, I get the feeling that this is breaking new ground and establishing these rules, not handling previously-established rules. I don't know where the rules are documented, and I'm not understanding what is going on. That's my real issue with this. |
@gdt I've made the code changes requested and included an attempt at documenting both the preexisting fields in the mappings dictionary as well as the new
The For context, I chose the word "value" because the new field is used to perform a comparison against the value associated with the key from the MQTT rtl message. "value" could also be changed to another term if you think there is a word or phrase that better conveys the purpose of the field ("match", "value_match", "value_equals"). |
Since the new conditional logic in this PR seems like it might be a bit of a sticking point, I thought it would be worth searching for other ways to automatically discover these Govee water sensors without altering the matching logic in this script at all. As alluded to in other comments, the main challenge with these sensors is that they write sensor-specific data in the generic
When the button on the sensor is pressed to indicate that the leak has been investigated and resolved the following message is published to the rtl MQTT topic:
Given the way this script is currently written, in order to auto-detect these sensors we would add a new mapping entry which maps the This simple approach would correctly discover the water sensors. However, searching through the decoders in this codebase reveals that there are at least 6 different devices that publish data in the event key. This wouldn't be a problem if all these devices were water sensors -- unfortunately, they are not (the Honeywell decoder is for a window / door sensor, the Yale decoder is for a home security alarm protocol, etc). Therefore, adding an "event" mapping to the mappings dictionary without any additional code changes to this script would result in all these devices being incorrectly added as moisture sensors. To prevent the problem described in the paragraph above, it is necessary to add some logic to distinguish messages originating from this water sensor from messages originating from other non-water sensors. The solution proposed in this pull request is to add the ability to compare the data associated with a given key in an MQTT message against a predefined value and ignore otherwise matching keys whose value does not match. Specifically, the script only creates a binary moisture sensor device in home assistant if the value of the event key is "Water Leak". As written, only one value can be specified per key but the code could be extended to support multiple different predefined values in the future (so that the other sensors using the event key could be auto-discovered as well). Alternate Solution -- Modify govee.cNow that the details behind why the new conditional logic is needed have been explained, it's clear that mapping the Govee water sensors directly to the "event" key can't be done without some change to the body of the script. The only way to work around this without changing the script logic would be to change the Govee decoder to emit leak information on a new, "moisture sensor specific" key (e.g. something like "leak_status", "water_sensor_status", etc). I'm not sure if a change to the decoder like this would be allowed or not, perhaps someone who has worked on that layer could comment (maybe @zuckschwerdt?). On the surface, this solution seems fine to me but I admittedly know nothing about how the decoded keys in the MQTT messages are derived so it's possible adding a new key would violate some of the rules or assumptions at that layer. Note that because many peoples' setups today certainly rely on the leak data being present in the If changing the decoder is preferred over the solution in this PR I'd be happy to give it a try (although I'd be even happier to test it with my Govee sensors if someone who already has already setup a build environment for the c code made the change). Looking forward to hearing thoughts/ideas from the repo maintainers on this so auto-discovery for this sensor can be merged soon one way or another! |
Normalizing keys in decoders is always appreciated. Contributors often start an implementation by matching keys and values to some random display because no prior work is available or visible enough. Perhaps some |
First, I want to say to @kcpants thank you for taking feedback seriously and revising. We are definitely making progress. And sorry for taking so long; this is complicated and I needed a good chunk of time to page this in. I agree (and putting my own spin on it) with @zuckschwerdt that in an ideal world we would have a clearer schema for the json output from rtl_433, and adjust that. My perhaps-too-hasty read is that we have key/value for keys that have semantics and values, like temperature, battery. But event: is not really a key in that sense with a value. It is really key event-foo and value "fired". The biggest question is if it's ok to modify The next question is about how this code works. I understand now that the general approach is that for each key in the json, an entity is created (unless it is skipped or not in the table), with many being diagnostic. The semantics now are that One possible modification that might help clarity and cleanliness is to preprocess the json by saying (with very poor pseudopython):
and then doing the normal mappings processing. This also leaves a nice path to do this inside each decoder, and then when that's complete, we can drop this stanza. I am not sure my suggestion is wise but would like to hear what y'all think. |
I realize now that my suggestion doesn't work as is, because we would have to also preprocess the json payload we send. So let me ask: how hard would it be to change the govee decode to emit event_waterleak:ON and event_waterleak:OFF instead? Or to use whatever values that the mqtt entity expects? And, are we creating a binary sensor, or are we creating distinct events? This is really stepping back and asking the bigger-picture "what kind of sensor is this really" question, but I'm now thinking that this path may not take very long at all and be better long term. I have a zwave leak sensor. It is a binary sensor: water detected vs water not detected. there is no ack button. Does the govee sensor send a "water no longer detected"? I wonder if this should be binary sensor for leak, and then a button for ack. But if there is no 'no longer detected', I'm not sure. Plus it seems like this would need a periodic "i'm ok, no leak, battery is x'" message to have this make sense. |
Looking at govee.c, I would say it deserves some updates, and I find it hard to follow. |
Adding a new output line is easy and compatible, we can keep everything else the same for some time, then drop the "old" event key. |
I wrote about the bigger picture on the mailinglist. |
It might be more efficient to use an We can use And to me
|
Event is the HA term. The fundamental problem is that a leak detector is logically a binary sensor: is it wet or is it not wet. But the govee, while it senses like this, does not report like this. It sends a "wet" message on not-wet to wet transition, and then every 5m thereafter while it is still wet. On a wet to not-wet transition, it just doesn't send any more. At least that's what I understand from the comments. This is IMHO a broken design, and it takes a state machine and timers to turn it back into the binary sensor it ought to be. It is especially tricky to do this when there is packet loss. And, we know rtl_433 doctrine says that time-based processing is improper; we just emit representations of received messages. I don't think it's always there. There are multiple codepoints in a field, and if that isn't "wet", then that particular message doesn't have a "it is wet" state. That might be because it's a battery report, or because it is reporting something else. HA seems to use event for things like button press. A 'it is wet" report is sort of like this. But it is sort of not. The right fix is to have the state machine (with timers) in between. The alternative is to kludge it into HA entities via representing "wet" as an event and have another entity (binary sensor) be true if there has been a wet event in the last 17 minutes (as an example). My conclusion from all this is not to buy any govee stuff! |
is anyone trying to make this work with HA? I just need to decide whether to return these sensors. |
You can use the changed rtl_433_mqtt_hass.py from this PR and it will "just work" (given an initial wet trigger I assume?) |
Thanks! And sorry for asking what probably should be obvious but how do I go about incorporating this change into HA? |
I finally figured out how to replace the rtl_433_mqtt_hass.py file in the rtl_433 autodiscovery addin in HA. I restarted it and I caused a water leak transmission but although there is a Govee-water-29010 device, there are no entities (e.g., event) from the payload. MQTT explorer shows the mqtt received by HA. |
Can you please share how you replaced the rtl_433_mqtt_hass.py file in the rtl_433 autodiscovery addin in HA? |
Sure. In order to access the mqtt_auto_discovery container, I installed Portainer and accessed the container and the console. From there I just did a wget to retrieve the file. If you need more details, just ask. However, I still can't make any use of the Govee sensors which is my objective. |
Ha. Your question made me go back and check the file, and lo and behold, though I had replaced the file, apparently it gets replaced with the old version when I restart the add-in. How do I replace the addin and have the new file? |
@Vlad-Star Every time I take a step forward (and think I have it working) I take 1 (or 2) steps backward. I added a second Govee sensor. It works fine but now the first sensor says "unavailable". I can see the MQTT messages from it in Explorer but HA no longer sees it. The only change I made was to mqtt.yaml. I copied the definition of the first sensor and changed the id and name: %cat mqtt.yaml binary_sensor: |
@Vlad-Star you're a gem, thank you for patiently troubleshooting with all of us! People like you keep our community moving forward. I didn't have MQTT auto-discovery on, as soon as I turned it on and pressed the button on the sensor, a new entry line pops up in MQTT explorer and a device pops us. I can also see the battery entity, not pictured here: but I went into entities and deleted the entry regardless to start over and make sure everything gets paired correctly from the get go. I also emptied out mqtt.yaml.
I followed the rest of the steps in order. For documentation's sake I will include some logs snippets. After completing steps 1 through 5, the MQTT Auto Discovery showed the following when I pressed the button:
With my rtl_433.conf looking like this:
I then added the following to
at which point I see the following: A success! |
@Jsalas424 that's great! I will be interested to hear what happens if you add a second sensor definition in your mqtt.yaml file. As I just reported I added a second sensor and it works fine but the first one is now unavailable. |
I found my problem with adding the 2nd sensor. It was a syntax problem in mqtt.yaml. As you can see in my post above, I had binary_sensor twice. The working version looks like this:
|
@ifuchs I am glad I helped you to figure out the problem :) (though this PR wasn't really right place for such a discussion - I apologize to the other folks for so many comments) |
@Vlad-Star thanks again. It would've taken forever without your help. |
I finally got caught up on the comments above. It looks like we are still waiting for the govee driver to be adapted, and then this can be adapted and then we can re-review. |
Correct. When the other PR is merged the change in this file will be simplified to a new mapping entry and the new
|
For reference the PR to add the normalized key is #2625. |
With the change to The new change is much simpler than the original. I think the main discussion-worthy points are the name and suffix that will be used for binary moisture sensors in HA.
|
I am not yet using this script, but the change looks good to me -- so I'm +1 on merging after a positive test report. Thanks very much for bearing with us. It was a long slog but I think the end result is much better! |
No worries, the first iteration of the solution in this pull request was hacked together under the assumption that the json keys were unchangeable. I'm glad to have been able to dig into the details and I agree that the solution we all converged on is much cleaner. Sorry for the slight delay here -- I'm testing this code within the With the underlying PR merged, the change in this PR works as expected. I've attached screenshots below for reference. To test I deleted all of my manually added Govee moisture sensors, ran the new version of I also had 2 brand new leak sensors which still contained the battery pull tab. For some reason simply pulling the battery tab to activate the device was enough for a water leak entity and a battery entity to be added to HA. I didn't capture the json but I assume this means the very first message ever sent by the device includes both |
I'm not having as much luck as you are. I get a battery entity, but no water entity. My MQTT Explorer does reflect a new "detect_wet" field AND my Auto Discovery logs show that being captured correctly but then ignored:
To test this, I performed the following:
but I don't have the water sensor data: Edit: I proceeded to grab a fresh version of |
@Jsalas424 What steps did you take to replace the contents of the I have been testing this by logging into the |
@kcpants I only uninstalled and reinstalled, I thought the change had merged. Sorry! |
I cleaned up the commit history in my clone of the repo to prepare for merging. Given the test results included in the comment above, I don't believe there is any unaddressed feedback on the current version of the fix contained in this PR. @zuckschwerdt I'm happy to make changes if folks have more suggestions, otherwise I think this is ready to go in. |
@gdt I think this pull request may have slipped through the cracks. It did get a bit noisy with all the comments pertaining to the underlying problem so perhaps zuckshwerdt muted the thread after leaving this comment and hasn't seen the latest updates? At this point it's not clear to me what needs to be done to get this merged. Perhaps it would help to try contacting someone with write access to the repo using a channel other than the comments in this particular pull request? I'd really like to see this closed so please let me know if there's anything I can do to help! |
I don't know if this thread is "dead" but I am having problems (again) getting the Govee leak sensors working. This was working but I had to move from running on a Mac Mini to a Windows system (both running VirtualBox) and it is possible that something was lost along the way. I am running rtl_433 on a Raspberry Pi and sending MQTT messages to HA. I have many Acurite temperature sensors and all of them are working fine via rtl_433 _> MQTT _> HA. When I press the button on the Govee I can see it is received by the rtlsdr and sending mqtt to HA. However, MQTT Browser does not show these messages. I am running MQTT Auto Discovery on HA although these devices already exist and are properly defined in mqtt.yaml. Any ideas about how to figure out where this is failing? P.S. I was going to delete this comment but I found the problem and just in case anyone makes the same (silly) mistake (unlikely but possible) here is what happened. I was being inundated with new devices being defined in HA so I finally turned off auto discovery and then to reduce the load on the MQTT broker, I added several -R [protocol #] parms to the rtl_433 command running on the RPi in order to accept only certain device types. Unfortunately, I forgot one protocol...the Govee leak sensor. So those messages were being duly ignored at the RPi. I added that protocol back in and voila, HA sees the sensors again. |
This PR adds support for auto-discovering Govee water leak detectors and configuring them as binary moisture sensors. Moisture sensor configuration fields are modeled after the existing alarm and tamper binary sensors. This code has been tested with Govee Water Leak Detectors model H5054.
As discussed in #2404, some versions of the these Govee water sensors report a
leak_num
field while while others do not. This change attempts to address both versions of the sensor by relying on theevent
field instead. Since theevent
field is present in many different sensors' data, it is necessary to examine the contents of the field to verify that the mqtt data does indeed pertain to a water sensor. The logic to compare the contents of a field to a predetermined value has been added generically and could be used to aid in the discovery of other sensors in the future.Note: The logic in
bridge_event_to_hass
was originally written as follows:However, this prevents keys associated with a mapping that has a value field whose value field does not match from being added to the
skipped_keys
list so it was necessary to combine the new conditional logic with the main if statement.