Qolsys IQ Panel 2 and 3rd party integration

Just set this up a few days ago! Excited about the way you’ve figured out how to reverse-engineer the remote panel connection. It’s been working great so far. Still need to migrate automations to this integration

This project is absolutely fantastic!

I just got it installed and I’m genuinely impressed. Not only did it detect all of my devices flawlessly, but it even successfully integrated my smoke detectors, something I struggled with on the Qolsys Gateway project.

Huge thanks to the developers. I’m really looking forward to putting this through its paces!

You can check with v0.0.22-beta.3 in HACS

Added support to trigger Police, Auxilliary and Fire Alarm through integration linked services. Services need to be enabled on integration page options.


@EHylands hey, happy to test this for you however I have a few questions can I use this in parallel with the existing control 4 integration? Also I have an iq2 panel not a two +, as far as I remember the two plus supports power G otherwise it’s the same so will it work for a non-2 plus? Thanks

EDIT: so, yes, this works with a regular IQ2 panel in beta 30. Pairing took 5 seconds. Nice!


Great news !
As per official qolsys specs, IQ Remote are only supported on IQ2+ panels…

Integration can be run in parallel with either C4 integration or alarmdotcom integration without any unique_id collision in Home Assistant.

Yes I’m really happy this is working. My panel is about 8 years old and it’s been flawless knock on wood I haven’t had to replace it yet so I’m just going to go along with it.

There’s a couple of blocking call logs I’ll submit an issue at your repo but so far everything is working perfectly here.

P.S. I do have two IQ panel remotes already this will be a third.

There seems to be a theoretical limit on how many IQ Remotes can connect to the main panel at the same time (3?).

One interesting thing I noticed: if you delete the Home Assistant virtual IQ Remote from the panel’s list, you can still connect using the client certificate that was already created. It doesn’t look like the main panel actually revokes the client certificate when the remote is deleted from the list.

IQ Remotes are really useful for discovering new capabilities. That’s actually how I was able to reverse the protocol, by issuing commands on the remote and listening to what gets published on the MQTT server.

If you run into issues or find bugs, please submit them on the GitHub page.

Tnx for helping out !

The two main blocking issues I’m aware of right now:

1- Zeroconf handling while pairing:
The controller uses its own Zeroconf instance, while Home Assistant would like me to use its own. WIP.

2- AIOMQTT client / certificate loading
The controller uses AIOMQTT as an async MQTT client, but Home Assistant doesn’t provide a helper to avoid blocking while loading certificates. Because of this, I’ll likely need to move the entire main function into an executor thread instead of running it directly as an asyncio coroutine. Also still WIP :slightly_smiling_face:

oh, interesting @EHylands! it must be at least 3 IQ Remotes, because I just tested my 2 real IQ Remotes and the virtual remote (i.e. your integration), simply arming and disarming and eveything is working and communicating with eachother, including the Q4 and alarm.com. Eventually, if your integration proves stable, I will switch because its first one I’ve seen that has sensor battery information!

Perhaps i don’t have to submit an issue, but the 2 logs I received (are very long) and seemed to have happened on parining, which if its a one off, probably ok, but I know event loop block is bad for HA, but here’s the logs with redacted pki values and 0xXXX.

Are these logs what you’re seeing?

Logs
Logger: homeassistant.util.loop
Source: util/loop.py:137
First occurred: 5:57:45 PM (2 occurrences)
Last logged: 5:57:45 PM

Detected blocking call to load_cert_chain with args (<ssl.SSLContext object at 0xXXXXXXXX>, '/config/qolsys_panel/pki/[REDACTED].secure', '/config/qolsys_panel/pki/[REDACTED].key', None) inside the event loop by custom integration 'qolsys_panel' at custom_components/qolsys_panel/config_flow.py, line 130: await self._QolsysPanel.mqtt_connect_task( (offender: /usr/local/lib/python3.13/site-packages/paho/mqtt/client.py, line 1285: context.load_cert_chain(certfile, keyfile, keyfile_password)), please create a bug report at https://github.com/EHylands/ha-qolsys-panel/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#load_cert_chain Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/__main__.py", line 229, in <module> sys.exit(main()) File "/usr/src/homeassistant/homeassistant/__main__.py", line 215, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 289, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.13/asyncio/base_events.py", line 712, in run_until_complete self.run_forever() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 683, in run_forever self._run_once() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 2050, in _run_once handle._run() File "/usr/local/lib/python3.13/asyncio/events.py", line 89, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request resp = await request_handler(request) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_app.py", line 569, in _handle return await handler(request) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_middlewares.py", line 117, in impl return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 81, in forwarded_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware response = await handler(request) File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle result = await handler(request, **request.match_info) File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin return await func(self, request, *args, **kwargs) File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 234, in post return await super().post(request, flow_id) File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper return await method(view, request, data, *args, **kwargs) File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post result = await self._flow_mgr.async_configure(flow_id, data) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 346, in async_configure result = await self._async_configure(flow_id, user_input) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 393, in _async_configure result = await self._async_handle_step( File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 493, in _async_handle_step result: _FlowResultT = await getattr(flow, method)(user_input) File "/config/custom_components/qolsys_panel/config_flow.py", line 130, in async_step_pki_autodiscovery_2 await self._QolsysPanel.mqtt_connect_task(
Detected blocking call to load_verify_locations with args (<ssl.SSLContext object at 0x7XXXXXXXXX>, '/config/qolsys_panel/pki/[REDACTED].qolsys') inside the event loop by custom integration 'qolsys_panel' at custom_components/qolsys_panel/config_flow.py, line 130: await self._QolsysPanel.mqtt_connect_task( (offender: /usr/local/lib/python3.13/site-packages/paho/mqtt/client.py, line 1293: context.load_verify_locations(ca_certs)), please create a bug report at https://github.com/EHylands/ha-qolsys-panel/issues For developers, please see https://developers.home-assistant.io/docs/asyncio_blocking_operations/#load_verify_locations Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/src/homeassistant/homeassistant/__main__.py", line 229, in <module> sys.exit(main()) File "/usr/src/homeassistant/homeassistant/__main__.py", line 215, in main exit_code = runner.run(runtime_conf) File "/usr/src/homeassistant/homeassistant/runner.py", line 289, in run return loop.run_until_complete(setup_and_run_hass(runtime_config)) File "/usr/local/lib/python3.13/asyncio/base_events.py", line 712, in run_until_complete self.run_forever() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 683, in run_forever self._run_once() File "/usr/local/lib/python3.13/asyncio/base_events.py", line 2050, in _run_once handle._run() File "/usr/local/lib/python3.13/asyncio/events.py", line 89, in _run self._context.run(self._callback, *self._args) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request resp = await request_handler(request) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_app.py", line 569, in _handle return await handler(request) File "/usr/local/lib/python3.13/site-packages/aiohttp/web_middlewares.py", line 117, in impl return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 81, in forwarded_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware return await handler(request) File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware response = await handler(request) File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle result = await handler(request, **request.match_info) File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin return await func(self, request, *args, **kwargs) File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 234, in post return await super().post(request, flow_id) File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper return await method(view, request, data, *args, **kwargs) File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post result = await self._flow_mgr.async_configure(flow_id, data) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 346, in async_configure result = await self._async_configure(flow_id, user_input) File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 393, in _async_configure result = await self._async_handle_step( File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 493, in _async_handle_step result: _FlowResultT = await getattr(flow, method)(user_input) File "/config/custom_components/qolsys_panel/config_flow.py", line 130, in async_step_pki_autodiscovery_2 await self._QolsysPanel.mqtt_connect_task(

By the way, is it normal for each sensor entitiy name to called Zone 1, 2, etc.? When I think of a zone, I think like an area that could have many sensors, but could be a Qolsys thing that im not sure of.

Yes, the blocking call you reported is the one related to aiomqtt. It only blocks one time when the integration is loading tls certificates.

  • Zones are individual sensors (binary sensor + battery sensor + signal sensor in HA)
  • Partitions are what you are refering to as areas

You will also find:

  • Z-Wave devices
  • Virtual or ADC devices (can read virtual ADC garage door status, but not control them yet …)

Fantastic! Ok, im all set here. Monitoring beta related issues and will report if i see anything.

Cheers

Thanks @EHylands, this works almost right out of the box. I installed it last evening, and tested some basic functions. So far, no issues or concerns to report back.

Edit: Forgot to add that I have an IQ 4 panel, one z-wave lock. The rest of my sensors are secure 319.5 Mhz that I had purchased from the alarm company.
I was unable to use any of them with HA, until yesterday.

Thank you @ranjitrajkumar
I’m very happy with the progress we made so far with everyone submitting their own config file. There is now support for PowerG security sensors advanced features, Z-Wave generic support, PowerG devices (locks,lights and maybe more) and Alarm.com virtual devices !

Next milestone I’m aiming for is to publish all those different device protocols under an unified interface to Home Assistant.

This looks great. I’d been resistant to using the mqtt + appdaemon route because I just didn’t want to install appdaemon and I don’t relay like using MQTT as the interface in HA (I prefer native integrations). So I was debating for a couple years if I had time to write an integration between the ones I’m already working on, but now I don’t have to.

I have an IQ Pro panel of which I only see one other mention in this thread.

Just put them behind config flow option with a warning confirmation step. That’s what I do with power control options that can violate utility interconnect agreements for my solaredge-modbus-multi integration. Default off with a big warning to turn on. For anyone using alarm.com without central station monitoring such commands carry zero risk except for potentially scaring someone with a loud siren. For those that do have central station monitoring, well, they were warned.

Hi @WillCodeForCats,

Another user reported successfully pairing with the IQ Pro Panel through the installer app.

I’ve added configuration options to trigger alarm , fire , and auxiliary alarm through the options flow. I’ll also take a look at your integration to find the most appropriate way to include a disclaimer. :slightly_smiling_face:

So the way I did it is have one option to bring up the warning and on the next step with the warning those actually enable the thing being warned about.

User selects Power Control Options and then submit:

Then they get the warning and have to select which group to enable (in this case one is a battery group and the other is an inverter group):

If the user doesn’t choose one of the two enable options then the power control options on the first step does nothing by itself.

So for the IQ if I were designing it I would have the main option be “Enable Alarm Triggers” as the last option at the bottom of the list and then on the next step with the warning put the three options for enable police/fire/aux.

Something to consider for the future: Qolsys rebranded to IQ in July 2025. It might confuse new users that buy newer products with integrations that mainly refer to old branding.