Interlogix Ultrasync

It seems that the various integrations are the same hardware/firmware with different brand names.

These alarm systems where sold from GE I thing in the beginning and it seems that they have been sold from one company to another during the course of years and changed names only.

The interface is the same as it seems. The options that are available differ on the kind of account that you log in with. If you log in as an installer you get more options.
Also, if you log in as an installer you can choose what settings the users can/see change. It also depends if you put the alarm in program mode (you get more options).

I would be happy with the ability to get notified with an armed/disarmed status, as I want to set other devices accordingly.

The ability to arm/disarm at a specific time of day is available already in the alarm system, but it is not considered a safe practice.

I use the App for my smartphone Interlogix Ultrasync. So the systems are the same.

Using sudo and install just doesn’t work on an raspberry pi using home assistant os :wink:

Edit time:

I made a docker version of Home Assistant and added ultrasync! It shows up in my integrations. Sadly, can’t add my data. I get an unexpected error

2020-11-06 07:09:52 ERROR (MainThread) [homeassistant.components.ultrasync.config_flow] Unexpected exception
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/ultrasync/config_flow.py", line 68, in async_step_user
await self.hass.async_add_executor_job(
File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/src/homeassistant/homeassistant/components/ultrasync/config_flow.py", line 38, in validate_input
if not usync.login():
File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 143, in login
if not self._areas(response=response) or not self._zones():
File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 418, in _areas
sequence = json.loads(match.group('sequence'))
File "/usr/local/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/usr/local/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/lib/python3.8/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

This is what the debug dump gives me

/usr/src/homeassistant # ultrasync --config=/root/stef/config.conf --debug-dump
2020-11-06 07:12:13,918 - ERROR - Failed to query http://192.168.0.247/login.cgi
2020-11-06 07:12:13,918 - ERROR - Failed to authenticate to 192.168.0.247

Just wanted to thank all those that emailed me and the few that private messaged me here! It’s amazing all the help you’re all offering! I will hopefully have more time to look at this tonight and/or this weekend. One major difference between our two panels is the zones.htm file.

UltraSync zones.html

Here is what mine looks like (and this is what my tool currently parses):

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>UltraSync :: Secure Network</title>
  <meta name="viewport" content="initial-scale=1.0, width=device-width, maximum-scale = 1.0, minimum-scale = 1.0" />
  <script src="/v_ZW_03.02-C/eng_us.js" charset="utf-8"></script>
   <link href="/v_ZW_03.02-C/m.css" rel="stylesheet">
  <script src="/v_ZW_03.02-C/master.js" charset="utf-8"></script>
  <script src="/v_ZW_03.02-C/status.js" charset="utf-8"></script>
 
</head>
<body onload = "afterLoad();">
  <script>
  var zoneDisplay = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

  var zoneNames = ["Sensor%20No1","Sensor%20No2","Sensor%20No3","Sensor%20No4","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21","%21"];
  var zoneSequence = [108,0,2,77,12,100,0,12,0,14,175,91,0,0,0,0,26,0];
  var zoneStatus = ["000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","040200000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","000000000000000000000000","E0F2FFFFFFFFFFFFFFFFFFFF"];
  var ismaster = 1;
  var isinstaller = 0;
  
  function getSession(){return "158BE52A55BFF0A0";}
...

Comnav zones.htm

Here is what the ones who are getting the JSON error:

<!doctype html>
<html>
<head>
  <meta charset="ISO-8859-1">
  <title>ComNav :: Secure Network</title>
  <meta name="viewport" content="initial-scale=1.0, width=device-width, maximum-scale = 1.0, minimum-scale = 1.0" />
  <link href="/v_CN_0.106-j/m.css" rel="stylesheet">
  <script src="/v_CN_0.106-j/master.js" charset="utf-8"></script>
  <script src="/v_CN_0.106-j/status.js" charset="utf-8"></script>
</head>
<body onload = "afterLoad();">
  <script>
  var zoneDisplay = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
  var zoneStates = new Array("Not Ready", "Tamper", "Trouble","Bypass","Inhibited","Alarm","Low Battery","Supervision Fault"
    ,"","","","","","");

  var zoneNames = new Array("","","","","","","","","","","","","","","","");
  var zoneSequence = new Array(27,0,0,0,239,182,0,0,0,0,129,0,0,0);
  var zoneStatus = new Array(new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0),new Array(0,0));

  function getSession(){return "87FCE66F5B718C96";}
...

For the non-developers, I’m just letting you know the problem we will have to solve (and no doubt it will happen) is how to figure out the connection between the 2 very differently presented variables (for the same hardware). Specifically have a look at the zoneSequence and zoneStatus variables (see how they differ above). I’m pretty sure the zoneSequence is apples to apples to the other (just presented slightly differently). The zoneStatus is a different ball game though.

I think under the hood, I can use the /v_CN_xx.xx-y/ as a switch. Depending if it’s a CN or a ZW I’ll have to parse these 2 variables differently.

There are other minor differences too which shouldn’t have a negative outcome to our goals such as:

  • the encoding… utf-8 vs iso-8859-1
    • This is worth keeping in the back of our head as Python v3 (what HA uses) is all utf-8. So any special characters that exist in Area/Sensor assignments could cause a crash later on. First round of fixing this I’m going to ignore this, but to keep in the back of our mind to support all character sets.
  • the NX-595 doesn’t tell you on the first page if you’re the installer and or a master account.
    • At this time, this info is nice to have but not useful for our purposes

seq.json

Some more details I’d like to have from you all If one of you guys could also log into your NX-595 and use your browsers Network Console (this is part of Chrome/Firefox’s developer tools) and have a look for a file that repetitively gets updated and requested called seq.json. I would love for someone to email me or private message me a copy of this too. This file plays an important roll in getting status updates.

status.json

If a sensor get’s tripped in your house, this will be reflected in the seq.json file. But a request to status.json is then made to get more details on the change that took place when this happens. So to get a copy of this file, you’ll just need to wave your hands in-front of a sensor; or open your front door or something. I’d really appreciate if someone can provide me a copy of there NX595 hub version of it.

Hi Chris. I have a ComNav branded system and am sending you the files mentioned via email today. The only point worth noting here I think is rather than a seq.json file, I appear to have a seq.xml file instead.

If you require further details just let me know. Thanks!

Hey Adam,

I have the Networx NX 595E. I assume that both are the same with only a different brand name. I also don’t have the seq.json. I already send all my files to Chris.

Chris will do his magic tricks :wink:

Hi all!

So this has turned out to be quite a massive change! :astonished:… I won’t lie; I spent more then 5 hrs today on it (I didn’t realize the time going by); I’m not done, but 3,300 lines of code later, i created my first Pull Request for it that should be testable by anyone feeling brave!

If you followed my instructions above, you’ll just want to uninstall your current copy of ultrasync and manually install the one from this branch instead:

# make sure it's not already installed (so you don't have any conflicts)
pip uninstall ultrasync

# Then install the branch version:
pip install git+https://github.com/caronc/ultrasync.git@comnav-compatibility

All of the commands are the same. Now please go easy on me: I don’t anticipate this is going to work the first time in Home Assistant.. But it should work… or at least allow us to troubleshoot it and work out the final details from the command line:

# dump system details from your alarm panel:
ultrasync -c /path/to/config.conf --details

# Also set up a watch if you want (i really don't think this will work for long):
ultrasync -c /path/to/config.conf --watch

# This might even work this time:
ultrasync -c /path/to/config.conf --debug-dump

Again, i want to re-iterate, this was a really big change… Not only was the zones.htm different between our alarm panels, but as you all observed and told me, it operates on XML files (not JSON). So i had to write a lot of additional XML parsing for seq.xml, status.xml, etc. The banks are parsed way differently too which made even more work… :sweat:…

Anyway… Since i don’t have the alarm panel; i need all of your help here to report back here (or in the Pull Request I made) what happens :slight_smile:.

I also want to thank everyone again who emailed me and or private messaged me some of their status files. :+1: I was able to create some unit tests too with this code as a result. :tada:

Finally, I’d love if someone could click on the Zones link after signing into their Hub’s webpage (must be via ComNav) and trip a sensor or two… That will cause your device to send you a zstate.xml file (I’m guessing, because my panel sends me a zstate.json file). I’d like to have this file; i believe it should provide me the only missing puzzle piece i need (no promises) to complete this task (and add more testing).

I look forward to hearing back from any of you and hearing about any update success and failures!

Hi Chris,

Looks like lots of progress! Thanks again for putting in all that time. Here is an update for you.

~$ /home/bryan/.local/bin/ultrasync -c ultrasync/config.conf --watch
2020-11-08 08:07:59 [001] MasterBed Motion        : Ready
2020-11-08 08:07:59 [001] Living Room Motion      : Ready
2020-11-08 08:07:59 [001] Kitchen/DiningMotion    : Ready
2020-11-08 08:07:59 [001] Theater Motion          : Ready
2020-11-08 08:07:59 [001] Hallway Motion          : Ready
2020-11-08 08:07:59 [001] Activity Room Motion    : Ready
2020-11-08 08:07:59 [001] Workshop Window Vib     : Ready
2020-11-08 08:07:59 [001] Front Door              : Ready
2020-11-08 08:07:59 [001] Garage Door             : Ready
2020-11-08 08:07:59 [001] Workshop Door           : Ready
2020-11-08 08:07:59 [001] Garage Window Vib       : Ready
2020-11-08 08:07:59 [001] siren tamper            : Ready
2020-11-08 08:07:59 [001] Alfresco Door           : Ready
2020-11-08 08:07:59 [001] Theater Door            : Ready
2020-11-08 08:07:59 [001] Guest Bedroom           : Ready
2020-11-08 08:07:59 [001] Kids Room 1             : Ready
2020-11-08 08:07:59 [001] Laundry Door            : Ready
2020-11-08 08:07:59 [181] Home                    : Not Ready
---
Traceback (most recent call last):
  File "/home/bryan/.local/bin/ultrasync", line 8, in <module>
    sys.exit(main())
  File "/usr/lib/python3/dist-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/cli.py", line 190, in main
    results = usync.details()
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/main.py", line 451, in details
    if not self.update():
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/main.py", line 436, in update
    if not self._sequence():
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1305, in _sequence
    return getattr(self, '_{}_sequence'.format(self.vendor))()
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1409, in _comnav_sequence
    response = self.__get('/user/seq.xml', rtype=HubResponseType.XML)
  File "/home/bryan/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1540, in __get
    response = ET.fromstring(
AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getroot'

/home/bryan/.local/bin/ultrasync -c ultrasync/config.conf --details
{
  "areas": [
    {
      "bank": 0,
      "bank_state": [
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "name": "Home",
      "priority": 5,
      "sequence": 181,
      "states": {
        "armed": false,
        "chime": false,
        "exit1": false,
        "exit2": false,
        "partial": false
      },
      "status": "Not Ready"
    }
  ],
  "date": "2020-11-08 08:07:49",
  "user": {
    "is_installer": null,
    "is_master": null
  },
  "zones": [
    {
      "bank": 0,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "MasterBed Motion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 1,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Living Room Motion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 2,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Kitchen/DiningMotion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 3,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Theater Motion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 4,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Hallway Motion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 5,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Activity Room Motion",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 7,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Workshop Window Vib",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 8,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Front Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 9,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Garage Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 10,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Workshop Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 11,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Garage Window Vib",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 15,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "siren tamper",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 16,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Alfresco Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 17,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Theater Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 18,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Guest Bedroom",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 19,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Kids Room 1",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 20,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "Laundry Door",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    }
  ]
}

/home/bryan/.local/bin/ultrasync -c ultrasync/config.conf --debug-dump
2020-11-08 08:08:10,810 - ERROR - Failed to query http://192.168.1.145/user/rooms.htm
2020-11-08 08:08:11,042 - ERROR - Failed to query http://192.168.1.145/v_CN_0.108-m/zwave.js

And the response from 3 different sensors trips. Sensor A, Sensor B and then Sensor A again.

<response>
  <zstate>0</zstate>
  <zseq>188</zseq>
  <zdat>0,0,0,0,0,0,0,0,0</zdat>
</response>

<response>
  <zstate>0</zstate>
  <zseq>193</zseq>
  <zdat>4,0,0,0,0,0,0,0,0</zdat>
</response>

<response>
  <zstate>0</zstate>
  <zseq>196</zseq>
  <zdat>0,0,0,0,0,0,0,0,0</zdat>
</response>

Thanks Chris for all the hard work. My NX doesnt display any zone names due to the older firmware.
Here is the output of the two commands

ultrasync.conf --details

{
  "areas": [
    {
      "bank": 0,
      "bank_state": [
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "name": "Area 1",
      "priority": 5,
      "sequence": 185,
      "states": {
        "armed": false,
        "chime": false,
        "exit1": false,
        "exit2": false,
        "partial": false
      },
      "status": "Not Ready"
    }
  ],
  "date": "2020-11-08 13:39:11",
  "user": {
    "is_installer": null,
    "is_master": null
  },
  "zones": []
}

ultrasync.conf --watch

Also noticed that the Area 1 status is displaying the incorrect status. “Not Ready” it should be “No System Faults” or “Ready”

020-11-08 13:39:51 [185] Area 1                  : Not Ready
---
Traceback (most recent call last):
  File "/home/divyesh/.local/bin/ultrasync", line 8, in <module>
    sys.exit(main())
  File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/cli.py", line 190, in main
    results = usync.details()
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/main.py", line 451, in details
    if not self.update():
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/main.py", line 436, in update
    if not self._sequence():
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1305, in _sequence
    return getattr(self, '_{}_sequence'.format(self.vendor))()
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1409, in _comnav_sequence
    response = self.__get('/user/seq.xml', rtype=HubResponseType.XML)
  File "/home/divyesh/.local/lib/python3.8/site-packages/ultrasync/main.py", line 1540, in __get
    response = ET.fromstring(
AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getroot'
<response>
  <zstate>0</zstate>
  <zseq>17</zseq>
  <zdat>2,0</zdat>
</response>
<response>
  <zstate>10</zstate>
  <zseq>1</zseq>
  <zdat>0,0</zdat>
</response>

Hey Chris,

Contents of zstate.xml below for you as requested. Great work so far. Thanks!

<response>
<zstate>0</zstate>
<zseq>81</zseq>
<zdat>0,0,0,0,0,0,0,0,0</zdat>
</response>

With the new update I can do the following:

I can add the alarm as an integration to my HA test server. It reads the status of the area (ready, not ready). If I activate my alarm through my phone/browser it works.

Using the services that are provided doesn’t work. I assume those aren’t updated yet with the new version?

/config # ultrasync -c /config/config.conf --details
{
  "areas": [
    {
      "bank": 0,
      "bank_state": [
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ],
      "name": "Woning",
      "priority": 5,
      "sequence": 199,
      "states": {
        "armed": false,
        "chime": false,
        "exit1": false,
        "exit2": false,
        "partial": false
      },
      "status": "Not Ready"
    }
  ],
  "date": "2020-11-08 02:54:53",
  "user": {
    "is_installer": null,
    "is_master": null
  },
  "zones": [
    {
      "bank": 0,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "sabotage sirene",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 1,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "det nachthall",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 3,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "det wasplaats",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 4,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "det inkom",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 5,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "det living",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 6,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "det garage",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    },
    {
      "bank": 7,
      "bank_state": "00000000000000",
      "can_bypass": null,
      "name": "brand",
      "priority": 5,
      "sequence": 1,
      "status": "Ready"
    }
  ]
}
/config # ultrasync -c /config/config.conf --debug-dump
2020-11-08 02:56:19,950 - ERROR - Failed to query http://192.168.0.247/v_CN_0.108-j/zwave.js
/config # ultrasync -c /config/config.conf --watch
2020-11-08 02:57:12 [001] sabotage sirene         : Ready
2020-11-08 02:57:12 [001] det nachthall           : Ready
2020-11-08 02:57:12 [001] det wasplaats           : Ready
2020-11-08 02:57:12 [001] det inkom               : Ready
2020-11-08 02:57:12 [001] det living              : Ready
2020-11-08 02:57:12 [001] det garage              : Ready
2020-11-08 02:57:12 [001] brand                   : Ready
2020-11-08 02:57:12 [199] Woning                  : Not Ready
---

Thanks for all of your time and effort Chris!

Hi Guys,

Just providing you all another status update. I think I’ve got everything fixed except the most important bug that has plagued you all so far; that is the ‘Not Ready’ reading (in Area Report) that keeps coming up… :roll_eyes: . I’m going to need more time here; This is such a crazy part of the source code that makes no sense to me (so far). This is what i need to some how interpret; it’s all over my head so far (found in status.js in the function updateArea()) :exploding_head::

        while(areaString == "")
        {
            if(areaDisplay[i] >= areaStates.length)
            {
                var maxCount;
                
                if(areaCount > 1)
                    maxCount = (areaStates.length);
                else
                    maxCount = (areaStates.length + sysStatus.length);
 
                if(areaDisplay[i] >= maxCount) 
                {
                    if(((stexit1 & mask) != 0) || ((stexit2 & mask) != 0))
                        areaDisplay[i] = 3;
                    else
                        areaDisplay[i] = 0;
                }
                else
                {
                    areaString = sysStatus[areaDisplay[i] - areaStates.length];
                    areaDisplay[i]++;
                }
            }    
            else
            {
                var st =  parseInt(areaStatus[areaDisplay[i]+ byteindex],10);   

                if((st & mask) != 0)
                {
                    if((areaDisplay[i] != 2) || ((starm & mask) == 0 && (stpartial & mask) == 0))
                    {
                        areaString =  areaStates[areaDisplay[i]];
                    }
                    if(areaDisplay[i] == 7)
                        areaDisplay[i]++;
                }
                else if(areaDisplay[i] == 2 && (starm & mask) == 0 && (stpartial & mask) == 0)
                {
                    areaString =  "Not Ready";
                 }

                areaDisplay[i]++;
            }
        }

New Features

As far as new changes (for anyone grabbing the latest version of ultrasync via pip):

  • --scene will now support away, stay, and disable options now; thanks for pointing this out @stefdewilde! :+1:
  • added a new switch called --compressed-debug-dump which is the same as --debug-dump really… except that it goes ahead and pre-produces a zip file for me that you can share immediately (and easily). The zip file just contains a dump of all of your hub’s details (such as status.xml, zstate.xml, zones.htm, area.htm, seq.xml, etc. In the future; this will be a life line to be able to see what is going wrong and be able to help debug your scenario. It contains no private information (unless you consider sharing your zone names private). It grabs the equivalent .json files for Informix users.
  • To address @dd77, ComNav Setup of v 0.106 or less will list all sensors (since names can’t be assigned to them). To everyone else, they’ll still continue to only see their sensors.
  • I also updated the config file support to allow for URLs as well… So before (and still now) you could put a host: value of my.host.name or an ip address. Now you can ALSO put a hostname such as: https://secure.website/ You can also put https://user:[email protected] if there is something like reverse proxy there as well. I added this after @bojo was kind enough to give me remote read only access to his security panel (:pray: thank you very much!).

I know I’m beginning to sound like a broken record, but i do want to again thank those who have set me their configs, via email and/or private messages here. I also love being provided suggestions, ideas and your own point of views. So please don’t stop! :slightly_smiling_face:

I’ll continue to battle the Not Ready problem more (probably not tonight); i think this is the very last piece of the puzzle to get all ComNav users up and working. We’re almost there…

Edit: Just thought I’d also share with those using the ultrasync tool (helping me out), if you add -vvv you’ll greatly increase the verbosity of the script (incase you were interested what it’s doing). It gets REALLY noisy if you add a 4th -v (-vvvv); but also worth pointing that out too.

All status work! So I my humble opnion the integration works.

The ‘not ready’ status means the system is not armed so it’s not secured. All sensors are ready and working, but the system itself isn’t active.

Now my quest to add this to my Home Assistant OS (Supervisor) is on again haha. I tested everything with a docker in windows. Is there a possibility to add this as an CustomComponent or so? Like with HACS or some sort?

Keep up the good work, yes actually not ready means “not ready to arm”

I think i got it guys! The Not Ready bug is fixed. I get what both you (@stefdewilde and @panos2310) are saying about the status. But my Interlogix setup literally tells me exactly what the panel states. It says Ready, Armed Away, etc. I want yours to do the same! :slightly_smiling_face:

For ComNav users, the ultrasync tool was always saying it was Not Ready even in the cases that it was. For the HA integration, the area status produced by this tool is a 1:1 for the sensor you’ll gain access to once you get integrated. So i definitely wanted it to report properly for you guys! I think we’re in really great shape now though! Make sure to fetch the latest code changes! :tada:

I also created a separate section of unit tests for those with the ComNav panel of v0.106 and those with a newer model since they have some differences. Additionally i cleaned up the --debug-dump even more so that it provides a progress bar to those that use it. It just creates a .zip file now instead of a directory filled with stuff.

Is there a possibility to add this as an CustomComponent or so?

Yes, definitely! :slight_smile: but it’s not straight forward. But if you follow the crazy docker instructions above it will work for you just to test it out. Hopefully the code will get merged soon. The nice thing about having the core component of this integration outside of HA (in ultrasync project) is that it will be easy to patch/fix future changes and/or bugs you guys find. You won’t need to wait this lengthy approval period we’re going through now (to get it in HA) or wait for the ‘next’ release.

If you’re comfortable that ultrasync is working good for you (and i hear back from a few others saying the same thing), I’ll go ahead and bump the version of it and make it official.

I followed the crazy docker instructions, but it doesn’t work with a raspberry pi. I use a test server.

When I activated my alarm through HA on my test server, the status changed to ready. I tried some automations as well and all worked great and fast.

Let’s hope this gets added in HA soon so I can add more crazy automations haha.

Keep the good work Chris! Thanks!!

1 Like

Can confirm everything seems to be working well in my windows and virtualbox (linux) enviroments but can not get it to function in my dockerized version (Synology host) of homeassistant, even after spinning up a fresh container.

bash-5.0# ultrasync -c /config/usconfig.conf -w                                                                                                                                                                                
Traceback (most recent call last):                                                                                                                                                                                             
  File "/usr/local/bin/ultrasync", line 8, in <module>                                                                                                                                                                         
    sys.exit(main())                                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__                                                                                                                                           
    return self.main(*args, **kwargs)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main                                                                                                                                               
    rv = self.invoke(ctx)                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke                                                                                                                                            
    return ctx.invoke(self.callback, **ctx.params)                                                                                                                                                                             
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke                                                                                                                                             
    return callback(*args, **kwargs)                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/ultrasync/cli.py", line 190, in main                                                                                                                                            
    results = usync.details()                                                                                                                                                                                                  
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 369, in details                                                                                                                                        
    if not self.update():                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 345, in update                                                                                                                                         
    if not self.session_id and not self.login():                                                                                                                                                                               
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 143, in login                                                                                                                                          
    if not self._areas(response=response) or not self._zones():                                                                                                                                                                
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 418, in _areas                                                                                                                                         
    sequence = json.loads(match.group('sequence'))                                                                                                                                                                             
  File "/usr/local/lib/python3.8/json/__init__.py", line 357, in loads                                                                                                                                                         
    return _default_decoder.decode(s)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 337, in decode                                                                                                                                                         
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 355, in raw_decode                                                                                                                                                     
    raise JSONDecodeError("Expecting value", s, err.value) from None                                                                                                                                                           
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
bash-5.0# ultrasync -c /config/usconfig.conf -d                                                                                                                                                                                
Traceback (most recent call last):                                                                                                                                                                                             
  File "/usr/local/bin/ultrasync", line 8, in <module>                                                                                                                                                                         
    sys.exit(main())                                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__                                                                                                                                           
    return self.main(*args, **kwargs)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main                                                                                                                                               
    rv = self.invoke(ctx)                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke                                                                                                                                            
    return ctx.invoke(self.callback, **ctx.params)                                                                                                                                                                             
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke                                                                                                                                             
    return callback(*args, **kwargs)                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/ultrasync/cli.py", line 170, in main                                                                                                                                            
    print(json.dumps(usync.details(), indent=2, sort_keys=True))                                                                                                                                                               
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 369, in details                                                                                                                                        
    if not self.update():                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 345, in update                                                                                                                                         
    if not self.session_id and not self.login():                                                                                                                                                                               
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 143, in login                                                                                                                                          
    if not self._areas(response=response) or not self._zones():                                                                                                                                                                
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 418, in _areas                                                                                                                                         
    sequence = json.loads(match.group('sequence'))                                                                                                                                                                             
  File "/usr/local/lib/python3.8/json/__init__.py", line 357, in loads                                                                                                                                                         
    return _default_decoder.decode(s)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 337, in decode                                                                                                                                                         
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 355, in raw_decode                                                                                                                                                     
    raise JSONDecodeError("Expecting value", s, err.value) from None                                                                                                                                                           
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Still, amazing progress in just a few days Chris, thanks again.

Can you try running the same command again with :-vvvv in the command too? The output will get really busy; but i need to see what the last retrieved response from your panel was before it crashed on you.

# same command with added verbosity:
ultrasync -c /config/usconfig.conf -d  -vvvv

Keep me posted! :slightly_smiling_face:

easy done.

bash-5.0# ultrasync -c /config/usconfig.conf -d -vvvv                                                                                                                                                                          
2020-11-10 04:15:07,729 - TRACE - Config: host loaded as 192.168.1.145                                                                                                                                                         
2020-11-10 04:15:07,729 - TRACE - Config: user loaded as USER                                                                                                                                                                 
2020-11-10 04:15:07,730 - TRACE - Config: pin loaded as PIN                                                                                                                                                                   
2020-11-10 04:15:07,730 - INFO - Authenticating to 192.168.1.145                                                                                                                                                               
2020-11-10 04:15:07,730 - TRACE - POST Request to http://192.168.1.145/login.cgi                                                                                                                                               
2020-11-10 04:15:07,979 - TRACE - URL: http://192.168.1.145/login.cgi, status_code: 200                                                                                                                                        
2020-11-10 04:15:07,980 - TRACE - URL: http://192.168.1.145/login.cgi, response:                                                                                                                                               
<!doctype html>                                                                                                                                                                                                                
<html>                                                                                                                                                                                                                         
<head>                                                                                                                                                                                                                         
        <meta charset="UTF-8">                                                                                                                                                                                                 
        <title>ComNav :: Secure Network</title>                                                                                                                                                                                
        <meta name="viewport" content="initial-scale=1.0, width=device-width, maximum-scale = 1.0, minimum-scale = 1.0" />                                                                                                     
        <link href="/v_CN_0.108-m/m.css" rel="stylesheet">                                                                                                                                                                     
        <script src="/v_CN_0.108-m/master.js" charset="utf-8"></script>                                                                                                                                                        
        <script src="/v_CN_0.108-m/status.js" charset="utf-8"></script>                                                                                                                                                        
        <script src="/v_CN_0.108-m/lang_engau.js" charset="utf-8"></script>                                                                                                                                                    
                                                                                                                                                                                                                               
</head>                                                                                                                                                                                                                        
<body onload = "afterLoad();">                                                                                                                                                                                                 
        <script>                                                                                                                                                                                                               
        var areaDisplay = new Array(0);                                                                                                                                                                                        
                                                                                                                                                                                                                               
                                                                                                                                                                                                                               
        var areaNames = new Array("Home","%21","%21","%21","%21","%21","%21","%21");                                                                                                                                           
        var areaSequence = new Array(204);                                                                                                                                                                                     
        var areaStatus = new Array(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0);                                                                                                                                                         
        var sysStatus;                                                                                                                                                                                                         
        var areaCount = 0;                                                                                                                                                                                                     
    var allAway = false;                                                                                                                                                                                                       
    var allStay = false;                                                                                                                                                                                                       
    var allChime = false;                                                                                                                                                                                                      
    var allpriority = 6;                                                                                                                                                                                                       
    var allSequence = 0;                                                                                                                                                                                                       
                                                                                                                                                                                                                               
        function getSession(){return "B7B5AD44EB061FE5";}                                                                                                                                                                      
        </script>                                                                                                                                                                                                              
                                                                                                                                                                                                                               
        <div id="w">                                                                                                                                                                                                           
                <!-- buildBanner() inserts banner html here -->                                                                                                                                                                
                <!-- buildMenu() inserts status menu here -->                                                                                                                                                                  
                <!-- buildAreas() inserts areas html here -->                                                                                                                                                                  
        </div>                                                                                                                                                                                                                 
                                                                                                                                                                                                                               
        <script>                                                                                                                                                                                                               
        sysStatus = new Array();                                                                                                                                                                                               
                                                                                                                                                                                                                               
        function afterLoad()                                                                                                                                                                                                   
        {                                                                                                                                                                                                                      
            convertNames(areaNames);                                                                                                                                                                                           
                hillsBuild = true;                                                                                                                                                                                             
                variant = 3;                                                                                                                                                                                                   
                buildBanner("ComNav");                                                                                                                                                                                         
        buildMenu(1,0,1,1,1,1);                                                                                                                                                                                                
                buildAreas();                                                                                                                                                                                                  
                                                                                                                                                                                                                               
                for(var i = (17*12); i < areaStatus.length;i++)                                                                                                                                                                
                        sysStatus.push(areaStatus[i]);                                                                                                                                                                         
                setTimeout("updateAllAreas()",1500);                                                                                                                                                                           
                areaSequence[0] += 100;                                                                                                                                                                                        
                setTimeout("pollSequence()", 100);                                                                                                                                                                             
        }                                                                                                                                                                                                                      
            // function called by iPhone to return "{active menu index, authorised menu list}"                                                                                                                                 
    // Note: the iPhone will display in the order presented here. see master.jss                                                                                                                                               
    function getMenu()                                                                                                                                                                                                         
    {                                                                                                                                                                                                                          
        if(hillsBuild)                                                                                                                                                                                                         
                return "[0, [1,1,1,1,1,1,1,1,0,0,0,0,1]]";                                                                                                                                                                     
        else                                                                                                                                                                                                                   
                if(variant == 1)                                                                                                                                                                                               
                        return "[0, [1,1,1,1,1,1,0,0,0,0,0,0,1]]";                                                                                                                                                             
        else                                                                                                                                                                                                                   
                return "[0, [1,1,1,1,1,1,0,1,0,0,0,0,1]]";                                                                                                                                                                     
    }                                                                                                                                                                                                                          
                                                                                                                                                                                                                               
        </script>                                                                                                                                                                                                              
</body>                                                                                                                                                                                                                        
</html>                                                                                                                                                                                                                        
                                                                                                                                                                                                                               
2020-11-10 04:15:07,981 - INFO - Retrieving initial Area information.                                                                                                                                                          
Traceback (most recent call last):                                                                                                                                                                                             
  File "/usr/local/bin/ultrasync", line 8, in <module>                                                                                                                                                                         
    sys.exit(main())                                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__                                                                                                                                           
    return self.main(*args, **kwargs)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main                                                                                                                                               
    rv = self.invoke(ctx)                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke                                                                                                                                            
    return ctx.invoke(self.callback, **ctx.params)                                                                                                                                                                             
  File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke                                                                                                                                             
    return callback(*args, **kwargs)                                                                                                                                                                                           
  File "/usr/local/lib/python3.8/site-packages/ultrasync/cli.py", line 170, in main                                                                                                                                            
    print(json.dumps(usync.details(), indent=2, sort_keys=True))                                                                                                                                                               
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 369, in details                                                                                                                                        
    if not self.update():                                                                                                                                                                                                      
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 345, in update                                                                                                                                         
    if not self.session_id and not self.login():                                                                                                                                                                               
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 143, in login                                                                                                                                          
    if not self._areas(response=response) or not self._zones():                                                                                                                                                                
  File "/usr/local/lib/python3.8/site-packages/ultrasync/main.py", line 418, in _areas                                                                                                                                         
    sequence = json.loads(match.group('sequence'))                                                                                                                                                                             
  File "/usr/local/lib/python3.8/json/__init__.py", line 357, in loads                                                                                                                                                         
    return _default_decoder.decode(s)                                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 337, in decode
   obj, end = self.raw_decode(s, idx=_w(s, 0).end())                                                                                                                                                                          
  File "/usr/local/lib/python3.8/json/decoder.py", line 355, in raw_decode                                                                                                                                                     
    raise JSONDecodeError("Expecting value", s, err.value) from None                                                                                                                                                           
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Hi. Thank you for the great work. I have a NX-8E and wanted to know if this is a better option to integrate with HA. Was there any pros/cons comparison done?

@bojo, i just can not reproduce this at all. That is so weird; the page you shared works great for me. It’s like your copy of Python 3.8 on your Synology isn’t properly parsing regular expressions properly…:confused: . Can run:

# get the full version of Python on your Synology device
python -V

Do you have an opportunity to upgrade/downgrade Python v3.8 to an older or newer version which may fix your issue? As per my side, i can gracefully handle that error, but without the sequence, you won’t be able to get your alarm details (so i’d only be making your error just a little more graceful looking; you’re still going to have a problem at the end of the day :slightly_frowning_face:.

@2devnull unfortunately i can’t answer your question here. At the start of this thread, i could say with certainty this code works with the Informix UltraSync ZeroWire setup, as of now i think I’m almost good to go with Hills ComNav users as well. I don’t know what the NX-8E web interface looks like. Hopefully someone else here will have some advice for you.