Qolsys IQ Panel 2 and 3rd party integration

Hey there!

I’ve been trying to get all the information and understand how to set things up. I’ve been using ad-qolsys from hacs, setup mosquitto + appdaemon + homeassistant as docker containers. Things are promising, but if all my sensors are being detected in homeassistant, they all have a status of “Unavaiblable”.

Using the MQTT integration “configure” I can see that the states are being updated properly though:

Message 12 received on mqtt-states/binary_sensor/door_patio/state at 1:43 AM:
Closed
QoS: 0 - Retain: false
Message 11 received on qolsys/panel/zone_event at 1:43 AM:
{
    "event": "ZONE_EVENT",
    "zone_event_type": "ZONE_ACTIVE",
    "version": 1,
    "zone": {
        "status": "Closed",
        "zone_id": 2
    },
    "requestID": "8be70c28-58bc-4458-9064-xxxxxxx"
}
QoS: 0 - Retain: false
Message 10 received on mqtt-states/binary_sensor/door_patio/state at 1:42 AM:
Open
QoS: 0 - Retain: false
Message 9 received on qolsys/panel/zone_event at 1:42 AM:
{
    "event": "ZONE_EVENT",
    "zone_event_type": "ZONE_ACTIVE",
    "version": 1,
    "zone": {
        "status": "Open",
        "zone_id": 2
    },
    "requestID": "4e508df3-fc37-423e-9e36-xxxxxxx"
}
QoS: 0 - Retain: false

I tried restarting things to see the initial payload:

Message 28 received on homeassistant/binary_sensor/door_patio/config at 2:09 AM:
{
    "name": "Door Patio",
    "device_class": "door",
    "state_topic": "mqtt-states/binary_sensor/door_patio/state",
    "payload_on": "Open",
    "payload_off": "Closed",
    "availability_mode": "all",
    "availability": [
        {
            "payload_available": "online",
            "payload_not_available": "offline",
            "topic": "mqtt-availability/binary_sensor/door_patio/availability"
        },
        {
            "payload_available": "online",
            "payload_not_available": "mqtt-client/status",
            "topic": "mqtt-client/status"
        }
    ]
}
QoS: 0 - Retain: false

Where you can see the topic given for the state corresponds to the one that has the status change above. But even then: nothing. And this even with these two messages right after:

Message 30 received on mqtt-availability/binary_sensor/door_patio/availability at 2:09 AM:
online
QoS: 0 - Retain: false
Message 29 received on mqtt-states/binary_sensor/door_patio/state at 2:09 AM:
Closed
QoS: 0 - Retain: false

Which should have initialized the state of the sensors…
Same situation with all my sensors from the Qolsys IQ Panel 2.

Any idea what might be the problem?
Thanks!

I’ve seen some weird behaviour on my side as well, which seems to line up with the fact that Retain is set to False on MQTT messages sent from ad-qolsys. But I’ve also noticed that some of my sensors aren’t showing up at all due to the fact that the device_class is empty when some sensor types are configured.
I’ll be opening 2 issues on the git repo for this.

BTW, can you share your apps.yaml config?

This could be related to a problem I experienced due to how data is read from the socket. If you have a large number of zones the JSON that’s published may be corrupted due to truncation. I’ve got a pull request out that fixes the issue but it has not been integrated yet. Go ahead and give it a try and see if it solves the problems you are experiencing: Ensure that parsable JSON is read from the socket by using a delimiter rather than assuming that messages are complete by Pablo1 · Pull Request #20 · roopesh/ad-qolsys · GitHub

BTW, can you share your apps.yaml config?

Pretty much using the default one:

qolsys_panel:
  module: qolsys_client
  class: QolsysClient
  log_level: DEBUG
  mqtt_namespace: mqtt
  qolsys_host: <ip of my qolsys>
  qolsys_token: <token of my qolsys>
  # Optional parameters
  qolsys_port: 12345
  request_topic: qolsys/requests
  qolsys_info_topic: qolsys/panel/info
  qolsys_zone_update_topic: qolsys/panel/zone_update
  qolsys_zone_event_topic: qolsys/panel/zone_event
  qolsys_alarming_event_topic: qolsys/panel/alarming
  qolsys_disarming_event_topic: qolsys/panel/disarm
  qolsys_disarm_code: <disarm code>
  qolsys_confirm_arm_code: False
  qolsys_confirm_disarm_code: False
  qolsys_arm_away_always_instant: False

It’s weird because today it started to work. I start to believe that the retain=False might be the culprit, yes. I’ve realized also that if there is a special character in the name of the sensor, there will be issues getting them through. I have not investigated if it was caused by ad-qolsys or by the qolsys websocket itself.

Kinda off topic but this android app that some guys were talking about in early posts in this thread. Looks like its made to work with a custom MQTT alarm panel but anyway to get this android app to work with the qolsys panel using this MQTT integration? Wife would love a second Qolsys panel in kitchen but I don’t want to drop 200 on secondary panel

Yeah, and don’t drop $200 on a secondary panel - they’re garbage (disconnects often, all sorts of issues with them, etc).

As with the MQTT Alarm Panel, I guess it depends on how the topics are set up, not a bad idea… but it really needs to send the commands in the proper format.

You can change the mqtt topics in settings I think I will play with it some and see what I can get it ti do I’ll let you know.

Is there a way to attempt to disarm the alarm with whatever code was entered in HA? Right now the only way I found to get this working was to use a single code for HA and explicitly define it in apps.yaml, but I’d like to be able to disarm with different codes. Can this be done?

I wanted to use 3 codes and sometimes no code so my fix was to install Alarmo from hacs . It’s basically a build your own HA alarm panel. My setup is

  • ad-qolsys setup code not required
  • alarmo setup with 3 codes with no sensors so it’s basically a panel you can arm/disarm but won’t alarm.
  • created a node red flow to arm/disarm ad-qolsys on Alarmo status change. Also it arm/disarm Alarmo based on ad-qolsys status change.

My dashboards I have around house I place Alarmo panel and it arms/disarms with any of my codes.

My phones I don’t want to use passcode so my Mobile Dashboard I just place the ad-qolsys panel.

I’m pretty new HA user and I’m slightly confused.
I’ve set up ad-qolsys component as described.
I can see in AppDaemon logs like

2021-10-28 13:45:08.474116 DEBUG qolsys_panel: call_service: mqtt/publish, {'namespace': 'mqtt', 'topic': 'qolsys/panel/zone_event', 'payload': '{"event":"ZONE_EVENT","zone_event_type":"ZONE_ACTIVE","version":1,"zone":{"status":"Closed","zone_id":2},"requestID":"c40cfa2d-fcdc-42d6-8fe3-d2e2c7724529"}\n'}

My appdaemon.yaml looks like

---
secrets: /config/secrets.yaml
appdaemon:
    latitude: 123
    longitude: 456
    elevation: 789
    time_zone: "America/Los_Angeles"
    plugins:
        HASS:
            type: hass
        MQTT:
            type: mqtt
            namespace: mqtt
            client_host: 192.168.X.Y
            client_port: 1883
http:
  url: http://127.0.0.1:5050
admin:
api:
hadashboard:

My apps.yaml looks like

---
qolsys_panel:
    module: qolsys_client
    class: QolsysClient
    log_level: DEBUG
    mqtt_namespace: mqtt
    qolsys_host: 192.168.A.B
    qolsys_token: abcdef
    # Optional parameters
    qolsys_port: 12345
    request_topic: qolsys/requests
    qolsys_info_topic: qolsys/panel/info
    qolsys_zone_update_topic: qolsys/panel/zone_update
    qolsys_zone_event_topic: qolsys/panel/zone_event
    qolsys_alarming_event_topic: qolsys/panel/alarming
    qolsys_disarming_event_topic: qolsys/panel/disarm
    qolsys_disarm_code: 9999
    qolsys_confirm_arm_code: False
    qolsys_confirm_disarm_code: False
    qolsys_arm_away_always_instant: False

However I do not see any new entity/device in HASS.
I’m definitely missing something but can anybody please point to it?
Thank you in advance!

That’s not a bad idea. I have Alarmo as well as PAI (don’t ask)… so this may be my fix.

How are you syncing arm/disarm state between Alarmo and the IQPanel? Do you pass the codes through to the panel?

Thinking I might as well just keep the IQP2 as a PowerG translator for Alarmo :stuck_out_tongue:

Try restarting AD, or try restarting the IQPanel. I think this is a byproduct of the non-persistent MQTT availability messages.

Do you see the INFO message in debug?

Thanks!
Something from this helped:

  1. added auth to mqtt broker and setup user + password for appdaemon
  2. adding alarm panel to dashboard

after that panel entity appeared in the hass.
But now I’ve met mentioned issue when panel locks up and entity became unavailable.

So so far I see ability only to arm/disarm the panel.
Is there a way to access:
panel glass breaking sensor?
panel motion sensor?
I see messages like

2021-10-28 15:22:30.909466 DEBUG qolsys_panel: call_service: mqtt/publish, {'namespace': 'mqtt', 'topic': 'mqtt-states/binary_sensor/panel_motion/state', 'payload': 'Closed'}

So data of the sensors should reach hass. Do I need to parse messages in mqtt topic or is there an easy way to pass sensors to the hass?

Also is it possible to trigger siren manually?
Thank you!

Here I see: Fix MQTT sensor discovery device_class · Issue #21 · roopesh/ad-qolsys · GitHub
that at least sensors can be fixed pretty soon - they will be visible in the hass after resolving of the issue.

Question about siren is still there - it’s very loud and it would be great to leverage it.

I’m use Node Red to Sync them I can share my flow if you want.

Please do!

AFAIK, the only way to manually trigger the siren would be to trigger a panic.

That should work for me.
Do you know what JSON payload should be to trigger the panic?

This Flow with basic Sync of two alarm panels. Mine is a little more in depth it notifies me via sms if I forget to turn alarm on and auto arms at night if i forget to arm house. I’m going way to far down the rabbit hole with this SMS integration I’ve basically built a complete interface to my home via sms.

[
    {
        "id": "90bb1b08b04125aa",
        "type": "server-state-changed",
        "z": "e7d211156d0383e2",
        "name": "Qolsys State",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "exposeToHomeAssistant": false,
        "haConfig": [
            {
                "property": "name",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            }
        ],
        "entityidfilter": "alarm_control_panel.partition1",
        "entityidfiltertype": "exact",
        "outputinitially": false,
        "state_type": "str",
        "haltifstate": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "outputs": 1,
        "output_only_on_state_change": true,
        "for": 0,
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "data",
                "propertyType": "msg",
                "value": "",
                "valueType": "eventData"
            },
            {
                "property": "topic",
                "propertyType": "msg",
                "value": "",
                "valueType": "triggerId"
            }
        ],
        "x": 130,
        "y": 120,
        "wires": [
            [
                "f22e21c8742aad3e"
            ]
        ]
    },
    {
        "id": "f22e21c8742aad3e",
        "type": "switch",
        "z": "e7d211156d0383e2",
        "name": "Qolsys Switch",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "armed_home",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "armed_away",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "disarmed",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 3,
        "x": 320,
        "y": 100,
        "wires": [
            [
                "c0a946fd01cba45d"
            ],
            [
                "c1b3c30f8836a75b"
            ],
            [
                "1b258072b78bba2e"
            ]
        ]
    },
    {
        "id": "c0a946fd01cba45d",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Qolsys Armed Stay",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_arm_home",
        "entityId": "alarm_control_panel.alarmo",
        "data": "",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 590,
        "y": 60,
        "wires": [
            [
                "d3fd8aa38583bfc0"
            ]
        ]
    },
    {
        "id": "c1b3c30f8836a75b",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Qolsys Armed Away",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_arm_away",
        "entityId": "alarm_control_panel.alarmo",
        "data": "",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 640,
        "y": 120,
        "wires": [
            [
                "f328d1bdb476d896"
            ]
        ]
    },
    {
        "id": "1b258072b78bba2e",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Qolsys Disarmed",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_disarm",
        "entityId": "alarm_control_panel.alarmo",
        "data": "{\"code\":1123}",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 560,
        "y": 200,
        "wires": [
            [
                "950134d81a0dfe81"
            ]
        ]
    },
    {
        "id": "d3fd8aa38583bfc0",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 830,
        "y": 60,
        "wires": []
    },
    {
        "id": "f328d1bdb476d896",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 850,
        "y": 120,
        "wires": []
    },
    {
        "id": "950134d81a0dfe81",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 850,
        "y": 200,
        "wires": []
    },
    {
        "id": "b6182b4f5ac16050",
        "type": "server-state-changed",
        "z": "e7d211156d0383e2",
        "name": "Alarm0 State",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "exposeToHomeAssistant": false,
        "haConfig": [
            {
                "property": "name",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            }
        ],
        "entityidfilter": "alarm_control_panel.alarmo",
        "entityidfiltertype": "exact",
        "outputinitially": false,
        "state_type": "str",
        "haltifstate": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "outputs": 1,
        "output_only_on_state_change": true,
        "for": 0,
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "data",
                "propertyType": "msg",
                "value": "",
                "valueType": "eventData"
            },
            {
                "property": "topic",
                "propertyType": "msg",
                "value": "",
                "valueType": "triggerId"
            }
        ],
        "x": 100,
        "y": 500,
        "wires": [
            [
                "5ab55271bef5acdd"
            ]
        ]
    },
    {
        "id": "5ab55271bef5acdd",
        "type": "switch",
        "z": "e7d211156d0383e2",
        "name": "Alarmo Switch",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "armed_home",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "armed_away",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "disarmed",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 3,
        "x": 310,
        "y": 480,
        "wires": [
            [
                "a8b2f8aa01bbcad1"
            ],
            [
                "872e4f240a95286f"
            ],
            [
                "4d9832fd70bebedc"
            ]
        ]
    },
    {
        "id": "a8b2f8aa01bbcad1",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Alarmo Armed Stay",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_arm_home",
        "entityId": "alarm_control_panel.partition1",
        "data": "",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 580,
        "y": 440,
        "wires": [
            [
                "44b13d3eedabd367"
            ]
        ]
    },
    {
        "id": "872e4f240a95286f",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Alarmo Armed Away",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_arm_away",
        "entityId": "alarm_control_panel.partition1",
        "data": "",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 630,
        "y": 500,
        "wires": [
            [
                "b55bce4bd2091cfd"
            ]
        ]
    },
    {
        "id": "4d9832fd70bebedc",
        "type": "api-call-service",
        "z": "e7d211156d0383e2",
        "name": "Alarmo Disarmed",
        "server": "ec918dbd.b92e5",
        "version": 3,
        "debugenabled": false,
        "service_domain": "alarm_control_panel",
        "service": "alarm_disarm",
        "entityId": "alarm_control_panel.partition1",
        "data": "{\"code\":1123}",
        "dataType": "jsonata",
        "mergecontext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 610,
        "y": 560,
        "wires": [
            [
                "b4a567c925e19e6a"
            ]
        ]
    },
    {
        "id": "44b13d3eedabd367",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 820,
        "y": 440,
        "wires": []
    },
    {
        "id": "b55bce4bd2091cfd",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 840,
        "y": 500,
        "wires": []
    },
    {
        "id": "b4a567c925e19e6a",
        "type": "debug",
        "z": "e7d211156d0383e2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 840,
        "y": 580,
        "wires": []
    },
    {
        "id": "ec918dbd.b92e5",
        "type": "server",
        "name": "Home Assistant",
        "version": 1,
        "legacy": false,
        "addon": true,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": false,
        "cacheJson": true
    }
]