KeyMaster Z-Wave lock manager and scheduler

Ok so it took me a day to test it (I’m busy working :slight_smile: ) but while these values may show that they are now online nothing was reported back from the lock to HA

2021-02-09 23:43:36.126 INFO ZWAVE: Node 137: value updated: 98-0-latchStatus open => open
2021-02-09 23:43:36.126 INFO ZWAVE: Node 137: value updated: 98-0-boltStatus locked => locked
2021-02-09 23:43:36.127 INFO ZWAVE: Node 137: value updated: 98-0-doorStatus open => open

You can see I unlocked it manually (Had to open the door)
Locked it manually (Save on battery)
Unlocked it with my user code

But no alarmtype/level was sent back to the sensors in HA. I will continue to have patience

Thanks, I updated the Wiki to point out the numberbox card being needed

@TheFuzz4 Do you see the alarmtype and alarmlevel sensors for your lock?

Yeah I can see them but I don’t see any values being changed when I interact with the lock.

ah weird. I don’t know how to troubleshoot that. You don’t see any zwave_js_event events when you do that either? Truthfully you should see something in the logs at a minimum, but since you aren’t I’m not sure what’s going on

Hmm, I’m not getting any events coming through when I set/reset usercodes through keymaster or through manually calling the zwave_js.set_lock_usercode service in the developer tools. I confirmed that I have the config/packages/additional_yaml/zwave_js.yaml file. I do get events coming through on lock/unlock, but not on set/clear user codes.

There aren’t any notifications/events set up for setting/resetting usercodes. I believe TheFuzz was trying to catch lock and unlock events

Yeah thats what I"m trying to catch which I think will also be tied back to the number of times a code can be used as well. My container did update this morning (3 hours ago) but I did unlock my front door this morning and can confirm that while my entities are enabled and do show up in the UI they are not reporting any values as of yet.

I’m trying to figure out what’s going on with notifications.

I’m still using the native z-wave integration until i either have more time or a better migration path is in place to switch to zwave_js.

I am getting valid data from my schlage lock.
alarm level is reporting the code slot (1,2,3,4 etc)
alarm type is reporting either an 18 (lock), 19 (unlock), 22(manual inside unlock), 21( manual inside lock)

The notifications worked when i first added, but it seems the past few updated broke the notifications. I still receive notifications, but I get this type of data

Unknown Alarm Type Value Champ
(where Champ is the name of the user defined for the code slot)

i do have the sensors properly defined in the integration UI.

interestingly enough, I am getting a proper message when the schlage lock button is pressed to lock the door (“frontdoor RF Lock” “frontdoor RF Unlock”)

I’ve been trying to comb through the key-master files, looking for where the alarm type and alarm levels are referenced, but i’m not a coder and a bit over my head in there.

any ideas?

So if you look at your sensor in HA
image
Notice that there is now a Value field down there. This is an attribute of the state so in your automation you need to read what that attribute is. Let me know if this makes sense to you.

So good news here. We are getting something back in the events being sent to HA now

{
    "event_type": "zwave_js_event",
    "data": {
        "type": "notification",
        "domain": "zwave_js",
        "node_id": 137,
        "home_id": 4120971940,
        "device_id": "28392b12774f07556ab5b5f018cdd57e",
        "label": "Keypad unlock operation",
        "parameters": {
            "userId": 1
        }
    },
    "origin": "LOCAL",
    "time_fired": "2021-02-10T22:29:40.754953+00:00",
    "context": {
        "id": "33785c6e43662b0ebf56fe60465296d4",
        "parent_id": null,
        "user_id": null
    }
}

So now I just need to figure out how in the world to parse this out so I can get my notifications of who unlocked the dang door. Need to do some research with appdaemon to figure out how to subscribe to events and then parse the json which means I guess I’ll be loading it into a dictionary and then parsing it out from there.
With this now coming in like its supposed to (I think) does this mean that if I set a usercode to say only be used 3 times the keymaster can now parse that and subtract like its designed to do? Just thinking you know like if a neighbor had to come over or something.

This should already be happening. Listen to the keymaster_lock_state_changed event and then try locking/unlocking your lock again, you should see a processed version of that event. In addition, we should already automatically decrease the access count with each event

Yep there it is code_slot and the magical number. Ok so now I need to figure out how to subscribe to these lol.

Is there a documented list of the other events that are exposed through the keymaster? Like mainly I’d like to know if someone is trying to punch in a bunch of wrong codes. There are sensors for this in the ZWaveJS2MQTT but they never clear themselves so they’re always triggered.

That’s the only event we capture. I will make a note to add something in the Wiki about it. Regarding those sensors, you could build an automation off a state change assuming it changes with every invalid attempt. If not I don’t know how we could track that

Yeah I hear you there. I’m hoping in future releases of zwavejs2mqtt the alarm_type and alarm_level get reported but for now I’ll take the win of being able to notify me of who unlocks the door.

For those of you who are curious as to how I handle my notifications for who unlocks the door I do it like so with appdaemon.
I am not going to show you how to setup an entire app for this but just show you the basics and you can take this and run with it however you desire

class lock_notifications(hass.Hass):
    def initialize(self):
          self.listen_event(
            self.door_unlock_notification,
            "keymaster_lock_state_changed",
            action_text="Keypad unlock operation",
        )

Now then whats going on here is I need to watch the HA event stream for any event that matches the “keymaster_lock_state_changed” event type and when we catch this event we fire off the function for the notification.

Now down here I gather up a bunch of stuff because I like logs and I like to spit out as much crap as I can into my logs so I know exactly what its doing/not doing.

I also handle my notifications here as you can see and it tells me what code the door was unlocked by. How do I know who unlocked the door? Simple the event data is all passed into this function for me in the data argument. So I just parse that argument and yank out the stuff that I care about. I get the usercode that was used and the name of who that code slot belongs to.

Also it should be noted that I was also using this automation with OZW before I moved over to zwavejs2mqtt so there is some evidence of the old still lingering in here. Like I used to have to lookup the user based on the code slot that was used but thanks to the devs here that is no longer needed. Anywho on with the show

So the function checks to see if anyone is home because that determines how this should be handled. I still want to be notified that the door was unlocked but I don’t need all the dramatics of say it was my neighbor coming over to feed the dogs while we’re out of town. I also take your picture if you unlock my door while we’re not home.


     def door_unlock_notification(self, event, data, kwargs):
        user_code = data["code_slot"]
        user_string = data["code_slot_name"]
        entity = data["lockname"]
        self.log("The lock %s was just unlocked by someone" % entity)
        self.log("The usercode that was used to unlock this lock is %s" % user_code)
        self.log("The user who unlocked this door is %s" % user_string)
        if self.get_state("group.all_persons") == "home":
            self.log("Somebody is home and the door unlocked so this is ok")
            message = "The front door was just unlocked by %s" % user_string
            self.notification(message)
        else:
            self.log("The lock was just unlocked by %s" % user_string)
            message = (
                "The front door was just unlocked by %s are they allowed to do this?"
                % user_string
            )
            speak_message = ("Hello there %s be advised that I have notified the home owners that you have unlocked the %s" % entity)
            self.run_in(self.audio_notification, 1, speak_message=speak_message)
            self.call_service(
                "camera/snapshot",
                entity_id="<CAMERA_ENTITY_ID>",
                filename="/config/www/cam_captures/outside_frontdoor.jpg",
            )
            filename = "/config/www/cam_captures/outside_frontdoor.jpg"
            self.run_in(
                self.notification_picture, 1, message=message, filename=filename
            )

These are all of the other functions that are called by this main function here to handle the notifications.
These functions actually live in a much larger script that I wrote for my alarm system so they get called by a lot of other things in the script than just who unlocked the door.

     def notification(self, message):
        self.call_service("notify/hangouts", message=message)

     def notification_picture(self, kwargs):
        self.log(
            "Debug: The message is %s and the filename is %s"
            % (kwargs["message"], kwargs["filename"])
        )
        for target in self.args["notificationID"]:
            self.call_service(
                "notify/hangouts",
                message=kwargs["message"],
                target=target,
                data={"image_file": "%s" % kwargs["filename"]},
            )

     def audio_notification(self, kwargs):
        speak_message = kwargs["speak_message"]
        self.call_service("homeassistant/turn_on", entity_id=self.media_player)
        self.call_service(
            "media_player/volume_set", entity_id=self.media_player, volume_level=0.65
        )
        self.call_service(
            "tts/cloud_say",
            entity_id=self.media_player,
            message=speak_message,
            options={"gender": "female"},
            language="en-AU",
        )
        self.call_service(
            "notify/alexa_media",
            target="group.alexa",
            message=speak_message,
            data={"type": "tts"},
        )

I hope that this helps you with your notification automation. Yes you can do this with the built in automation within HA and there might be some ways to set variables and recall them in your notifications so that you don’t have to write one automation per code slot but my HA yaml automation skills are not very good. In fact I use it mainly for really super simple automations and I use appdaemon for the heavy lifting. If you have questions about how or why I did something a particular way let me know. I’ll be happy to assist.

BTW if you want me to move this to its own thread of how to do notifications with keymaster let me know.

1 Like

Well for seemingly no reason at all, without me doing anything, the lock and keymaster seem to be communicating properly now and setting/clearing codes in the UI now promptly and accurately show as Connected/Disconnected.

You gotta love computers man

Is there anyone watching this thread still using ozw or zwave? I need some help testing a change I want to make to get rid of the need to do the pre-installation steps. If you fit this criteria and are interested in helping, DM me!

I have 2 be469 locks, using ozw, and don’t currently have keymaster installed (but could). I’ve just been waiting until I move to zwave_js to set it up.