Please Help! MQTT Lock Status Won't Update in HA, state_topic works

Hey guys,

Really hoping someone can help me out here, as I’ve spent the last 3 hours banging my head against the wall on this one. I’ve got a Schlage lock that’s set up and working in Hubitat, and I’d like to be able to integrate it into HA. I know there isn’t any “official” way to do this, so I chose to use https://github.com/jeubanks/hubitat-mqtt-bridge to set up a bridge and utilize my existing Mosquitto MQTT broker.

Everything seemed to go good and seems to work, except that I can’t for the life of my get HA to show the right status when the lock is operated from anywhere outside of HA (from Hubitat or manually at the door). Here are the relevant lines in my configuration.yaml:

mqtt:
  discovery: true
  broker: 192.168.1.14
  port: 8883
  tls_insecure: true
  certificate: /ssl/ca.crt
  client_id: homeassistant01_mqtt
  username: [redacted}
  password: [redacted}
  birth_message:
    topic: 'hass/status'
    payload: 'online'
  will_message:
    topic: 'hass/status'
    payload: 'offline'

#Front Door Lock  
lock:
  - platform: mqtt
    name: "Front Door Lock"
    state_topic: "hubitat/Front Door Lock/lock/state"
    command_topic: "hubitat/Front Door Lock/lock/cmd"
    payload_lock: lock
    payload_unlock: unlock
    optimistic: false
    qos: 1
    retain: false

And when HA boots back up, the lock can be locked & unlocked from it which is awesome! Unfortunately the “state” in HA dev tools shows this even though the lock is in fact locked…and even unlocking/locking it again never changes the state shown:

Finally, subscribing to the topic in HA yields the expected outcomes when operating the lock outside of HA:

image

But for some reason this same exact “state_topic” on the mqtt entity doesn’t see these updates. I should also mention that on my Mosquitto server I see state updates being sent to HA in the log, and I’ve tried just about every combination of the ‘optimistic’, ‘qos’, & ‘retain’ lines I can think of.

I feel like there HAS to be something super simple that I’m missing, as I’ll admit I’m a bit green with MQTT…but I just don’t understand what I’m missing. Can anybody suggest what I might be missing? Thank you!!

In “Listen to a topic” it shows the received payloads for the topic are:
locked
unlocked

However, in your lock’s configuration you have specified the following values for payload_lock and payload_unlock:
lock
unlock

They don’t match the ones shown in “Listen to a topic”.

Interesting…I thought the “payload_lock/unlock” related to the command_topic? I thought that mean the “payload” or command HA sent when using the command_topic…I very well might be misunderstanding that though.

The reason I did that was because the default values of LOCK & UNLOCK (all caps) cause locking/unlocking the lock from within HA to not work…but making them lowercase allowed that to work. Presumably because something is case-sensitive? What am I misunderstanding here, or how would I go about fixing that?

EDIT: So sure enough, changing to ‘payload_lock: locked’ and ‘payload_unlock: unlocked’ made it so the status gets properly reflected within HA. Unfortunately now I again cannot lock & unlock the lock from within HA. lol

It’s used for both the state and command topics.

The alternative to using payload_lock and payload_unlock is to use value_template. Create a template that converts the received payload.

Per the documentation, Home Assistant’s lock entity expects to receive LOCK and UNLOCK.

Alright…yeah I edited my reply above with more info.

I’m beyond terrible w/ value templates lol, but I’ll do some digging into that :slight_smile:

MQTT Switch lets you define a different state payload from the command payload. MQTT Lock doesn’t appear to, so if the payload for the state is different from that for the command you will need to change optimistic to true and just hope it works…

You could however configure a seperate binary sensor to reflect the lock state.

Or, instead of using optimistic mode, you could set up an automation that publishes the “lock” and “unlock” state topics when the binary sensor changes. I think that would work… :thinking:

Just set the values for payload_lock and payload_unlock to whatever is needed by the command topic and create a value_template that converts the received payload values to LOCK and UNLOCK.

For example, if the received values are locked and unlocked, this template will convert them to LOCK and UNLOCK.

    value_template: "{{value[:-2] | upper}}"

Much simpler thatn my suggestion, but because he has defined the payload_lock and payload_unlock (in other words they are no longer the default) would it be sufficient to do:

   value_template: "{{value[:-2]}}"

It probably doesn’t help that I’ve been messing with this so long that my head hurts haha, but I am in awe at your wizardry! I will try that now. I was trying

value_template: “{{ value | replace(‘locked’,‘LOCK’) }}”

and

value_template: “{% if value == ‘locked’ }LOCK{% else if value == ‘unlocked’ %}UNLOCK{% else %}unknown{% endif %}”

but neither or those seemed to work…

EDIT: Ok, so with

#Front Door Lock  
lock:
  - platform: mqtt
    name: "Front Door Lock"
    state_topic: "hubitat/Front Door Lock/lock/state"
    command_topic: "hubitat/Front Door Lock/lock/cmd"
    payload_lock: lock
    payload_unlock: unlock
    value_template: "{{value[:-2] | upper}}"
    optimistic: false
    qos: 1
    retain: false

I can still successfully lock & unlock the door from within HA, but the state in HA still always reports unlocked.

Follow zoogara’s suggestion and remove the upper filter from the template. It will then match the values you’ve specified in payload_lock and payload_unlock.

Got it! Just needed to change your ‘upper’ to ‘lower’!

So I realize this is a bit of a corner case, but on the off-chance that someone else finds themselves in a similar boat down the road, here is my final config:

#Front Door Lock  
lock:
  - platform: mqtt
    name: "Front Door Lock"
    state_topic: "hubitat/Front Door Lock/lock/state"
    command_topic: "hubitat/Front Door Lock/lock/cmd"
    payload_lock: lock
    payload_unlock: unlock
    value_template: "{{value[:-2] | lower}}"
    optimistic: false
    qos: 1
    retain: false

@123 Thank you so much for the prompt replies and patience with my noob questions, I really appreciate your help. It’s crazy smart people like you who make this community so amazing!

1 Like

Are sure you even need the lower filter? From the screenshot you posted, the received payloads (locked/unlocked) are already in lowercase.

That’s a good question…let me check :slight_smile:

EDIT: Confirmed, @zoogara your suggestion worked great too. The ‘lower’ piece is just redundant in this case. I can only hope to one day understand all this as well as you guys. Thank again, I really appreciate it!

Yeah - well done @123 - I definitely need to learn more about templating…

No worries, you will.

All that template does is just slice off the last two characters of the received value.

Makes sense, I was able to gather the slicing off from the syntax, it’s just finding an example somewhere to tweak that I would have had the problem with :slight_smile:

One more simple question - why does the value_template only apply to “unlocked” and “locked” messages, rather than also applying to the ‘lock’ and ‘unlock’ message values listed as payloads? Is it because those are sent values whereas the state_topic values are received?

As per the documentation for MQTT Lock, value_template is for extracting values from payloads (received by state_topic).

value_template
(string)(Optional)
Defines a template to extract a value from the payload.

Ok…so templates by their natures are for processing incoming data. I see now. Thanks!

Correct. If the template serves some other purpose then its name will reflect it:

service_template
command_template
brightness_value_template
json_attributes_template
etc