Aha! Here we actually coming to another level.
I’m currently porting my Kerui D026 door sensor from OMG RF to OMG Pilight.
Here’s the issue: Kerui D026 can send 4 different codes: opened, closed, tampered and low battery.
First two can be classes as “states”, where the last two are more of “attributes” (imho)
I think that it’s a good idea to have states retained, when attributes can be used as signals for automation or to temporarily change the current state.
Therefore, I use MQTT sensor to represent the door sensor’s state and take into account the tampered attribute. In fact, I use an additional template sensor mostly because MQTT sensor does not support icon_template
.
So here’s the raw MQTT sensor (you don’t need to add it to any view)
- platform: mqtt
name: contacts_1st_floor_safe_pilight
state_topic: 'home/contacts/1st_floor/safe'
json_attributes_topic: 'home/contacts/1st_floor/safe/attributes'
and its UI representation
- platform: template
sensors:
contact_1st_floor_safe:
friendly_name: !secret 1st_floor_safe_name
value_template: >
{% if is_state_attr('sensor.contacts_1st_floor_safe_pilight', 'tamper', 'on') %}
{{ states('sensor.contact_always_tampered') }}
{% else %}
{{ states('sensor.contacts_1st_floor_safe_pilight') }}
{% endif %}
icon_template: >
{% set state = states('sensor.contact_1st_floor_safe') %}
{% if state == states('sensor.contact_always_opened') %}
mdi:door-open
{% elif state == states('sensor.contact_always_closed') %}
mdi:door-closed
{% elif state == states('sensor.contact_always_tampered') %}
mdi:image-broken
{% else %}
mdi:cloud-question
{% endif %}
The thing is my demultiplexer listens to the OMG Pilight topic, extracts known codes if protocol is kerri_d026 and publishes to appropriate topics (home/contacts/1st_floor/safe for opened/closed and home/contacts/1st_floor/safe/attributes for tamper).
It kind of works, but I don’t like 2 things:
- Handling of Pilight messages. They come as JSONs, but the main info (unicode, state etc) is within
message
, something like this:
{"message":"{\"unitcode\":441825,\"state\":\"tamper\"}","protocol":"kerui_D026","length":"","repeats":2,"status":2}
I have to parse them myself in every script as it’s a string and there is no way to use something like value_json,message.state
. I yet to find a way to do it nicely. So for now it’s like
known_states = ['opened', 'closed']
known_attributes = ['tamper']
#known_states = stable_states + temporary_states
entity = None
state = None
# remove curly brackets and split into "key:value" strings
params = message.replace('{', '').replace('}', '').split(',')
# clean and store parameters - have to do ALL of them, awful!
for param in params:
key, value = param.split(':')
key = key.replace('"','')
if key == 'unitcode':
id = int(float(value))
for e in known_entities.keys():
if id in known_entities[e]:
entity = e
break
elif key == 'state':
state = value.replace('"','').lower()
if entity is None:
logger.debug('unknown entity, ignored')
elif state is None:
logger.error('no state information provided for %s, ignored', entity)
and only after that I can do something…
By the way, I don’t know who and why created this format of messages, but it would be great to make it either “plain” (one-level) JSON or JSON-able (i.e when message is formed as JSON as well).
- The way I handle that
tamper
attribute. I want the UI sensor to show “tampered” for a number of seconds instead of its state and then go back to it. That way my alarm panel would be activated as it can react not only onopened
, but ontamper
as well.
Currently I achieve that by publishing JSON {“tamper”:“on”} and then {“tamper”:“off”} to home/contacts/1st_floor/safe/attributes, but I have to add a delay between these 2 commands to make the change visible for a set amount of time. Don’t like it.
Any ideas how to improve that?
So all in all, there is no single solution, and it’s not that great and bright, but we are getting there