Hubitat Safety Monitor API

Having some problems getting this to work. Your sample is a good test code and when I run it my HSM armedState does not change? I updated the same to use the correct API as described in this thread.

Best
Sean

definition(
		name: "test 123",
		namespace: "hubitat",
		author: "Sean",
		description: "test 123",
		category: "Convenience",
		iconUrl: "",
		iconX2Url: ""
)

preferences {
    section {
    }
}

def installed() {
    initialize()
}

def updated() {
    initialize()
}

def initialize() {
	sendLocationEvent(name: "hsmSetArm", value: "armAway")
}

Maybe related but I do not see the Away, Home, Night sections? I tried uninstall HSM and same I have no sub section for Intrusion-Away, Home and Night as in this picture. Also how can I manually change the state from Home to Away via WEB interface?
docs hubitat com File:HSM_Intrusion-Away.png

Thanks!

Settings--> Location and Modes--> Mode tab

1 Like

Thanks! This is what I also found but wanted to be sure as the name was not "armedAway" or Armed anything :slight_smile:

This has Day, Evening, Night, Away. So Away would arm away what would arm stay? What if I am home but not armed what state would that be?

I am far from an HSM expert and my setup is pretty basic in comparison to others I'm sure. This is how I look at it.

The HSM modes are independent of the hub modes....but....hub modes can be tied to HSM modes.

I have my Away mode tied to my HSM Armed Away mode so they are essentially one in the same.....and Disarmed tied to every other state.

I use HSM in conjunction with the Mode Manager app as follows.
My Day and Evening (essentially Home) modes are set based on time and my Away mode is based on presence.
When I leave Mode Manager sets my hub to Away which in turn automatically sets my HSM to Armed Away.
When I return home Mode Manager sets it to either Day or Evening depending on the time of day. This automatically sets my HSM mode to Disarmed.

It gets a little more complicated with a few custom modes I have but that's personal to my setup.

1 Like

You can add your own custom modes. :grin:

When I now use the following call to change alarm state:

sendLocationEvent(name: "hsmSetArm", value: "armAway")

and then when I then get the status using:

location.hsmStatus

I always get back "disarmed"

This used to work. What am I missing?
Updated my hub today so that may be the problem. Hey @bravenel can you help?
This table shows that the armAway and armHome events are not registering as hsmEvent types

could that be the issue?

I need to know the sequence of events that caused those logs.

Each row was generated by invoking the following command from within my HousePanel app. I included a log print line right after it so that I knew what "cmd" was and it matches the string values shown in the log.

   sendLocationEvent(name: "hsmSetArm", value: cmd)
   logger("HSM arm set with cmd= ${cmd}", "info")

I even replaced cmd with a hard coded "armAway" just to see and it was added to the log but the HSM mode still didn't change. The only ones that seem to do anything is the disarmAll and armAll values when they are sent in the cmd value.

Just for kicks I added a statusHandler and subscribed to it in my init function and that doesn't fire either. And again it does fire for armAll and disarmAll but not for armAway or armHome or armNight.

The entire setHsmState routine is pasted below:

def setHsmState(swid, cmd, swattr, subid){

    def i
    def key = ""
    def cmds = ["armAway", "armHome", "armNight", "disarm", "armRules", "disarmRules", "disarmAll", "armAll", "cancelAlerts"]
    def keys = ["armedAway", "armedHome", "armedNight", "disarmed", "armedHome", "disarmed", "disarmed", "armedAway", "disarmed"]

    // first handle toggling on icon in gui using attr information
    // default is disarm if something isn't understood
    if ( subid=="state" && swattr && swattr.startsWith("hsm") ) {
        cmd = "disarm"
        for (defkey in keys) {
            if ( swattr.endsWith(defkey) ) {
                i = keys.indexOf(defkey) + 1
                if ( i >= keys.size() ) { i = 0 }
                cmd = cmds[i]
                key = keys[i]
            }
        }
        
    // handle commands sent by GUI
    } else if (subid.startsWith("_")) {
        cmd = subid.substring(1)
        i = cmds.indexOf(cmd)
        key = keys[i]

    // handle API commands sent by name
    } else if ( cmds.contains(cmd) ) {
        i = cmds.indexOf(cmd)
        key = keys[i]
    } else {
        cmd = false
    }
    
    if ( cmd && cmds.contains(cmd) ) {
        sendLocationEvent(name: "hsmSetArm", value: cmd)
        logger("HSM arm set with cmd= ${cmd}", "info")
    }
    
    def resp = getHsmState(swid)
    return resp
}

Am I supposed to be doing location.currentState(ā€œhsmStatusā€) instead?

location.hsmStatus

Okay that is what I am using. Any idea why the status doesnā€™t change after I make the function call with armAway or armHome?

I feel this may be a timing issue. The location.hsmStatus completes prior to the queued sendLocationEvent command.

I just tried this and received disarmed, however the hsmStatus changed to amingAway, then after the exit delay, armedAway

It may also be that the location object is not refreshed and has the original settings. I remember @bravenel mentioning using true option for currentValue to refresh, but have no idea how to do that with the location.hsmStatus command

Thanks for this. I will just keep track of the mode instead of asking the hub for it. Should be an easy fix for my app but I still think this type of workaround hack should not be needed.

I understand why you feel a work around should not be needed. My work history is serialized business code for Mainframe batch, Mainframe Online, then websites. When I first began coding in ST, I bumped into timing issues, also bumped into a timing issue a few days ago while working on an HE app.

HE is a real time system, likely with multi threading, perhaps multiple cores, not serial. So that SendLocationEvent once executed is not instantaneous, it first has to be queued, then processed, and removed from the queue, meanwhile your app continues processing. In this environment it's entirely possible that your request receives the previous state, or perhaps not. I've also never figured out if there is an Enq/Deque Groovy method for a resource, and even if there is such a method, we don't have access to the internal resource name.

1 Like

I still don't understand what is not working for you, or why. Haven't had a lot of time. Have you looked at Location Events?

RM is using this same interface and works as expected. After sending "hsmSetArm" with "armAway", HSM responds with a bunch of events (not sure why the duplicates -- worth looking into, but a separate matter).

The first event above (the bottom one) was from RM setting armAway. The other 4 are from HSM (as shown by "hsmEvent".

And after this sequence, location.hsmStatus is correct:

log.debug "hsmStatus=$location.hsmStatus"

debug hsmStatus=armedAway

And, HSM UI shows the correct state:

Try this in your test app, while your system is disarmed
sendLocationEvent(name: "hsmSetArm", value: "armAway")
def arm2=location.hsmStatus
log.debug "arm2: $arm2"

result is always disarmed (on my system)

Glad it is working in RM but it isnā€™t working for me. The sequence that @arnb describes matches what I see. I will fiddle with it again but I think it is an issue with my latest hub update. This behavior didnā€™t happen before I updated recently.

I reported that issue with a suggested system solution a few days ago.

This all arose from a developer request many months ago. I don't recall the specific reasons involved, and haven't had time to dig into it.

Your suggestion of not issuing armAway when state is armingAway makes no sense, as it must transition from armingAway to armedAway.

Revisiting this is not high on our list right now.