[Release] Envisalink Security (Vista ONLY) - Native Hubitat TPI Driver (No Proxy Required)

I'd used ChatGPT to debug a driver issue with Hubitat - it actually wrote a debug driver that isolated the issue and fixed it. So that got me thinking......I posed the issue of the Envisalink driver thrashing the security status between armed and disarmed in a multi-partition system.

It provided a one-line fix that IGNORES armed status for anything but partition 1.

So, in essence, it does nothing but makes the driver REALLY support only partition 1 and eliminates the crud from partition 2 thrashing status.

%00 message
     │
     ├─ determine partition number   ← Brian already did this
     │
     ├─ P1? ─ YES → update P1 + HSM
     │
     │
     └──────── NO  → don't update P1/HSM
     │
     ▼
process zone information             ← unchanged

    // ============================================================================
    // CHATGPT MODIFICATION - MP1
    //
    // PURPOSE:
    //   Brian Wilson's original 2.0.3 driver correctly parses the Vista partition
    //   number from each %00 Virtual Keypad Update into partitionNum. However, the
    //   original code below always updated the child device whose DNI ends in "_P1"
    //   and always notified the parent app for HSM synchronization, regardless of
    //   which Vista partition actually generated the %00 message.
    //
    // PROBLEM ON MULTI-PARTITION SYSTEMS:
    //   If Partition 1 is armed while Partition 2 is disarmed/ready, the periodic
    //   %00 messages from the two partitions can alternately report "armedaway"
    //   and "ready". Because both messages were sent to the same "_P1" child and
    //   to the parent HSM synchronization routine, Hubitat's Panel Status could
    //   alternate between the states of Partition 1 and Partition 2.
    //
    // MP1 DESIGN:
    //   The existing Envisalink Partition child and existing HSM integration are
    //   treated as representing Vista Partition 1 only. Therefore, only a %00
    //   message whose parsed partitionNum is 1 may update that child or notify
    //   the parent app of a partition-state change.
    //
    // IMPORTANT:
    //   We intentionally DO NOT return from handleKeypadUpdate() when a message
    //   belongs to another partition. Brian's existing zone-state machine below
    //   this block still receives and processes the %00 message exactly as before.
    //
    // SCOPE:
    //   No other driver behavior is changed by MP1. Commands, connection handling,
    //   zone processing, child creation, flag parsing, and all other TPI processing
    //   remain Brian Wilson's original 2.0.3 implementation.
    //
    // Added by ChatGPT - MP1 multi-partition status isolation
    // ============================================================================

    if (partitionNum == 1) {

        // CHATGPT MP1 DIAGNOSTIC:
        // Confirms that the partition-state information is being accepted as P1.
        ifDebug("CHATGPT MP1: Partition 1 state accepted: ${partState}")

        // Brian Wilson original behavior, now explicitly restricted to Partition 1.
        def partChild = getChildDevice("${device.id}_P1")
        if (partChild) partChild.partition(partState, alpha)

        // Brian Wilson original HSM synchronization behavior, also restricted to P1.
        // It remains suppressed briefly after sending a command to avoid the re-arm
        // feedback loop caused by panel state lag after disarm/arm.
        if (!state.cmdSentAt || (now() - (state.cmdSentAt as long)) >= 3000) {
            parent?.updatePartitionState(partState, alpha)
        } else {
            ifDebug("Suppressing partition update — cmd sent ${now() - (state.cmdSentAt as long)}ms ago")
        }

    } else {

        // CHATGPT MP1 DIAGNOSTIC:
        // The message is still allowed to continue into Brian's zone-state machine
        // below; only its partition-state/HSM effects are suppressed.
        ifDebug("CHATGPT MP1: Partition ${partitionNum} state ignored for P1/HSM: ${partState}")
    }

Would it be reasonable to update the Envisalink driver with this? It totally solved my partition thrash issue. (Although I've removed HSM it probably would fix that issue with status too...)

Give this branch a shot; it has multi-partition support which should address your issue.

App import url: https://raw.githubusercontent.com/bdwilson/hubitat/refs/heads/claude/envisalink-tpi-hubitat-6B3B2/Envisalink/Envisalink_App.groovy
Driver import url: https://raw.githubusercontent.com/bdwilson/hubitat/refs/heads/claude/envisalink-tpi-hubitat-6B3B2/Envisalink/Envisalink_Connection.groovy

There should be an app and a device preference:

Partition for arm status / HSM: Defaults to 1.

Multi-partition panels: only this partition's arm state updates the Security Panel device and HSM

If it works for you, I'll push the fix to the main branch. Appreciate your level of detail of the problem and your chatgpt fix which is the only way I (Claude) could have implemented it.

Brian

Thanks! I'm assuming that I could just save a copy of the app and driver that I have now, pop these in place, and then if it doesn't work, pop the original stuff back?

I'm not sure about that. I suspect the sensor devices may be re-created. If I was you, I'd create virtual devices for all of the motion/door sensors and use the Hubitat 'swap devices' function to back up your existing automations assigned to those devices to the virtual devices, then when the new version of the Envisalink app creates those new devices, you come back and swap devices from those virtual backups to the new devices. This should keep automations in place. I would take a backup of your Hub first just in case. If things work for you, I'll push this to the main repo for the app and further re-installations shouldn't need the 'swap devices' hoops.

It works VERY well!

I'm now able to:

  • Get accurate alarm information without it flipping back/forth
  • Get accurate device information without it flipping back/forth

I tested it without the system armed, it updated the status of devices in Partition 2 accurately as well as Partition 1.

I also armed the system. All the rules worked for Partition 2 with no problem.

Because I'm no longer running those 'debounce' routines to compensate for the status changing my hub is quite a bit more responsive.

As far as I'm concerned you can make this 'production'. Let me know when it's there and I'll use HPM to update to your 'official' vesion.

Thanks so much for all this great work,
j

Installing it on Hubitat when running an older version of this driver if NOT using Hubitat Package Manager:

  • Copy the driver code to the existing driver
  • Copy the app code to the application
  • Access the App, access Configure Zones and be sure to configure any sensors for Partition 2
  • Click DONE to re-initialize the app
  • All devices will remain the same
  • Go back and double-check Configure Zones to be sure zones are correct

If upgrading from the older driver by Doug Beard, my comments are:

  • Hubitat will NOT allow you to seamlessly replace virtual devices. Since all of the sensors exposed by the driver are virtual 'child' devices they can't be easily swapped.
  • I strongly recommend getting a SECOND Envisalink board if you don't have one. If nothing else you probably SHOULD have one as a backup. Temporarily connect this to your security system, assign an IP address so it can be used.
  • Go into your EXISTING older Envisalink device, click on Child Device, click on each Child Device and rename it, adding a character like "*" to the end of its name
  • Now all of your child devices will be device* (i.e. Living Room Motion*, Front Door Sensor*, etc.)
  • Install the updated Brian Wilson Envisalink driver
  • Access the application, configure it to use your the temporary BACKUP Envisalink board that you have
  • Configurate your zones with the same name as your existing zones MINUS the "*". (i.e. Living Room Motion, Front Door Sensor, etc.)
  • Start going down the child devices on your older Envisalink connection, open "child devices", open the first child device, click it's "in use by" tab and update each item using it. (i.e. this is likely your rules., etc.)
  • Test out each update that you make
  • Iterate through all devices.
  • At this point your older board should have all of it's child devices using nothing and it should also show as using nothing. You should be able to disable it.
  • Once it's disabled, you can go into the Brian Wilson Envisalink app, switch it's IP address to be the IP address that the older app was using
  • You may now remove the backup Envisalink board
  • Everything should be working. Once verified, disable and delete the older Envisalink Doub Beard driver so that you don't get confused with having it in your system.

Hope that helps others.

Regards,
j

Brian:

Did you ever consider processing %02 messages and adding them as a PartitionStateName, PartitionStateValue attributes of the driver? I’m thinking that it could be useful for folks who didn’t want to try to divine it from keypad messages that it sends.

Currently, you have to do text comparisons with the status message to get those. (i.e. CONTAINS “DISARMED”, CONTAINS “AWAY”, etc. Not very efficient.

For a range, you could use “PartitionStateValue” to say:

            If PartitionStateValue<”04”    - the partition is disarmed
            If PartitionStateValue=>"04" and PartitionStateValue <="06" - the partition is armed

            Or if you preferred

            If PartitionState contains “Ready” then – not armed etc.

From what I could find out, the %02 message is:

%02 — Partition State Change

Format: %02,<16 hex digits>

This allows for 8 potential partitions. The first 2 characters are state codes for partition 1, next 2 for partition 2. They are not hex values but codes as per the table below:

Code Partition state
00 Not used
01 Ready
02 Ready with bypassed zones
03 Not Ready
04 Armed Stay
05 Armed Away
06 Armed Instant
07 Exit Delay
08 Alarm
09 Alarm occurred / alarm memory
10 Armed Maximum

A message like this:
%02,0100010000000000$

Would mean:

Partition 1 = 01 = Ready
Partition 2 = 00 = Not used
Partition 3 = 01 = Ready
Partitions 4–8 = 00

Just wondering, if you were looking for another enhancement, etc.

I worked through this with Claude, the TPI spec and the pyenvisalink module that this was based on and he said: "My point was only that pyenvisalink ignores %02, and it's only sent when something changes. The keypad update (%00) already gives the same arm state, refreshed about every 10 seconds, so the %02 attributes add little and can go stale after a reconnect."

We did uncover a bug that you wouldn't run up against, so I've fixed that but will leave the features at that. Doing full multi-partition is a little more complex and I don't want to break this for people who only run 1.

You should be able to install this from HPM or grab the main ImportURL's to update; It did figure out how to solve your issue without a configuration option, so I've taken that one out.

I just updated with HPM and that version does NOT have partition information for zones!

Yikes!

It looks like the driver was updated but not the app that allows you to configure the zones.

It’s supposedly not needed anymore.

Oh, so you're saying that it takes zone assignments from the security panel and defaults to always use partition 1?

I updated with HPM and got some log errors with:error

groovy.lang.MissingMethodException: No signature of method: user_driver_bdwilson_Envisalink_Connection_999.addZone() is applicable for argument types: (java.lang.Integer, java.lang.String, java.lang.String, java.lang.Integer) values: [1, Kitchen Heat Detector, Smoke, 1]
Possible solutions: addZone(int, java.lang.String, java.lang.String) on line 134 (method addZone)

I found the 2.0.4 version of the Envisalink app that matched the 2.0.4 driver and that worked well, no errors, and had the option to select partition and assign zones to partitions.

All that being said, I think that it's wise to accept the partition from the panel - that IS the authoritative source - but would be nice to allow folks to choose which partition to use for HSM and report panel status.

But, like I said, I upgraded from Hubitat package manager and ...yikes....got those errors. Should I try again?

Yes please try from HPM again. Should be 2.0.5.

It worked. All is good! Thanks so much!!

Now happily running, I'd pose one (I hope last) question.

I need to determine armed/away/stay/disarmed etc., and am going through gyrations to do it. I COULD run HSM but I really don't want to use it and add that overhead.

Your driver determines status and feeds it to HSM. Could you add that item to the list of items that can be queried from panel status as something like "panelHSMStatus".

I'm thinking that would be a trivial change that would allow folks to know the state of the alarm and do things without having to glob on another package or do complex rule coding (like I'm doing).

I could make my rule condition: if panel status panelHSMStatus changes

Which would be ever so nice!

2.0.6 should have that value you can check

That is FANTASTIC! Thanks! I can now see when the alarm arming status changes without needing to parse all the stuff because it's now leveraging what you've already figured out in the driver.

Makes it a LOT simpler. Really appreciate the quick update.

The driver is light years of improvement over the "Doug" driver. Great new functionality with multi-partition support and ability to query "HSM status" without having to add HSM.

Again, appreciate the quick response!

(post deleted by author)