Skip to content

Commit

Permalink
Alarm control panel
Browse files Browse the repository at this point in the history
  • Loading branch information
roopesh committed Apr 7, 2021
1 parent 61740e0 commit 7b34a93
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 30 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ AppDaemon app for Qolsys IQ Panel 2 _for Home Assistant_. Only tested using the

Fully self-contained AppDaemon app. If you have HA MQTT Discovery turned on, you should end up with binary sensors for each `Door_Window` zone on the Qolsys panel. There are more zone types which I don’t own so I have not handled them in anyway.

You’ll also have an `alarm_control_panel` device in HA for each partition in your Qolsys panel.
You’ll also have an alarm_control_panel for each partition. If you use the alarm panel component in HA, you don't have to worry about sending commands to the panel. It'll all be auto-magiced with MQTT discovery.

Arguments in apps.yaml:
```
Expand All @@ -17,7 +17,9 @@ Arguments in apps.yaml:
# qolsys_zone_event_topic: (Optional) The topic to publish ZONE_EVENT events to; defaults to qolsys/zone_event
# qolsys_alarming_event_topic: (Optional) The topic to publish ARMING events to; defaults to qolsys/arming
# qolsys_disarming_event_topic: (Optional) The topic to publish DISARMING events to; defaults to qolsys/disarming
# qolsys_alarm_status_topic: (Optional) The topic to publish alarm status for the alarm_control_panel; defaults to qolsys/alarm/status
# qolsys_disarm_code: (Required - if you want to disarm the alarm)
# qolsys_confirm_disarm_code: True/False (Optional) Require the code for disarming; defaults to False
# qolsys_confirm_arm_code: True/False (Optional) Require the code for arming; defaults to False
```
You’ll need you appdaemon's apps.yaml to include an app with this module and class:
```
Expand All @@ -34,7 +36,9 @@ qolsys_panel:
qolsys_zone_event_topic: qolsys/panel/zone_event # Optional
qolsys_alarming_event_topic: qolsys/panel/alarming # Optional
qolsys_disarming_event_topic: qolsys/panel/disarm # Optional
qolsys_alarm_status_topic: qolsys/alarm/status # Optional
qolsys_disarm_code: 4567 # Optional - Required if you want to disarm the panel
qolsys_confirm_arm_code: False
qolsys_confirm_disarm_code: False
```
As far MQTT is concerned, I had to figure out how to enable MQTT inside AppDaemon. In case you’re new to AppDaemon and have the same questions, I had to put this in my appdaemon.yaml:
```
Expand Down Expand Up @@ -69,7 +73,7 @@ You can send commands to the Qolsys panel on the `request_topic` in the config (
{"event":"ARM", "arm_type":"away", "partition_id": 0, "token":"blah"}
# Disarm
{"event":"DISARM", "usercode":"0000", "token":"blah"}
{"event":"DISARM", "usercode":0000, "token":"blah"}
```
Known issues:

Expand Down
61 changes: 39 additions & 22 deletions apps/ad-qolsys/partition.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re

class partition:
def __init__(self, p_id: int, name: str, status: str):
def __init__(self, p_id: int, name: str, status: str, code: int, confirm_code_arm: bool, confirm_code_disarm: bool):
""" Arguments:
id: int
name: str
Expand All @@ -12,40 +12,57 @@ def __init__(self, p_id: int, name: str, status: str):
self.name = name
self.zones = set()
self.entity_id = re.sub("\W", "_", self.name).lower()
self.payload_on = "ARMED"
self.payload_off = "DISARM"
# self.payload_on = "ARMED"
# self.payload_off = "DISARM"
self.__c_disarmed__ = "disarmed"
self.__c_armed_home__ = "armed_home"
self.__c_armed_away__ = "armed_away"

self.config_topic = "homeassistant/binary_sensor/" + self.entity_id + "/config"
self.state_topic = "mqtt_states/binary_sensor/" + self.entity_id + "/state"
# self.config_topic = "homeassistant/binary_sensor/" + self.entity_id + "/config"
# self.state_topic = "mqtt_states/binary_sensor/" + self.entity_id + "/state"
self.alarm_panel_config_topic = "homeassistant/alarm_control_panel/qolsys/" + self.entity_id + "/config"
self.alarm_panel_state_topic = "mqtt_states/alarm_control_panel/qolsys/" + self.entity_id + "/state"
self.status = status
self.code = code
self.confirm_code_arm = confirm_code_arm
self.confirm_code_disarm = confirm_code_disarm

def alarm_config_payload(self):
payload = {
"name": self.name,
"code": 2102,
"state_topic": self.alarm_panel_state_topic,
"code_disarm_required": False,
"code_arm_required": False,
"code_disarm_required": self.confirm_code_disarm,
"code_arm_required": self.confirm_code_arm,
"command_topic":"qolsys/requests",
"payload_disarm":'{"event":"DISARM","token":"shw9s8", "usercode":2102, "partition_id":0}',
"payload_arm_home":'{"event":"ARM", "arm_type":"stay", "token":"shw9s8", "usercode":2102, "partition_id":0}',
"payload_arm_away":'{"event":"ARM", "arm_type":"away", "token":"shw9s8", "usercode":2102, "partition_id":0}'
"command_template":'{"event":"{% if action == \"ARM_HOME\" or action == \"ARM_AWAY\" %}ARM","arm_type":"{% if action == \"ARM_HOME\" %}stay{% else %}away{% endif %}"{% else %}{{action}}", "usercode":"' + str(self.code) + '"{% endif %}, "token":"shw9s8", "partition_id":"' + str(self.p_id) + '"}'
}
if self.confirm_code_disarm or self.confirm_code_arm:
payload.update({"code":self.code})
return payload

def config_payload(self):
payload = {
"name": self.name,
"state_topic": self.state_topic,
"payload_on": self.payload_on,
"payload_off": self.payload_off
}
return payload
# def config_payload(self):
# payload = {
# "name": self.name,
# "state_topic": self.state_topic,
# "payload_on": self.payload_on,
# "payload_off": self.payload_off
# }
# return payload

@property
def code(self):
return self.__code

@code.setter
def code(self, code: int):
self.__code = int()
try:
if int(code) and len(str(code))>=4:
self.__code = int(code)
else:
raise ValueError("Not a valid code")
except:
raise ValueError("Not a valid code")

@property
def status(self):
Expand Down Expand Up @@ -82,9 +99,9 @@ def remove_zone(self, zoneid:int):

def __str__(self):

me = ("id: %s, name: %s, status: %s, entity_id: %s, payload_on: %s, payload_off: %s, \
config_topic: %s, state_topic: %s, zones: %s" % (self.p_id, self.name, self.status, self.entity_id, \
self.payload_on, self.payload_off, self.config_topic, self.state_topic, self.zones))
me = ("id: %s, name: %s, status: %s, entity_id: %s, \
alarm_panel_config_topic: %s, alarm_panel_state_topic: %s, code: %s, zones: %s" % (self.p_id, self.name, self.status, self.entity_id, \
self.alarm_panel_config_topic, self.alarm_panel_state_topic, self.code, self.zones))
return me

def __repr__(self):
Expand Down
13 changes: 10 additions & 3 deletions apps/ad-qolsys/qolsys_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
# qolsys_zone_event_topic: (Optional) The topic to publish ZONE_EVENT events to; defaults to qolsys/zone_event
# qolsys_alarming_event_topic: (Optional) The topic to publish ARMING events to; defaults to qolsys/arming
# qolsys_disarming_event_topic: (Optional) The topic to publish DISARMING events to; defaults to qolsys/disarming
# qolsys_confirm_disarm_code: True/False (Optional) Require the code for disarming
# qolsys_confirm_arm_code: True/False (Optional) Require the code for arming
# qolsys_disarm_code: (Required - if you want to disarm the alarm)

class QolsysClient(mqtt.Mqtt):
def initialize(self):
Expand All @@ -43,10 +46,11 @@ def initialize(self):
self.__c_qolsys_arming_topic = "qolsys_alarming_event_topic"
self.__c_qolsys_disarming_topic = "qolsys_disarming_event_topic"
self.__c_qolsys_alarm_status_topic = "qolsys_alarm_status_topic"
self.__c_qolsys_disarm_code__ = "qolsys_disarm_code"
self.__c_qolsys_confirm_disarm_code__ = "qolsys_confirm_disarm_code"
self.__c_qolsys_confirm_arm_code__ = "qolsys_confirm_arm_code"

# populate some variables we'll need to use throughout our ap
# self.mqtt_broker = self.args[self.__c_mqtt_broker__]
# self.mqtt_port = self.args[self.__c_mqtt_port__] if self.__c_mqtt_port__ in self.args else 1883
# populate some variables we'll need to use throughout our app
self.mqtt_namespace = self.args[self.__c_mqtt_namespace__] if self.__c_mqtt_namespace__ in self.args else ""
self.qolsys_host = self.args[self.__c_qolsys_host__]
self.qolsys_port = self.args[self.__c_qolsys_port__] if self.__c_qolsys_port__ in self.args else 12345
Expand All @@ -59,6 +63,9 @@ def initialize(self):
self.qolsys_arming_event_topic = self.args[self.__c_qolsys_arming_topic] if self.__c_qolsys_arming_topic in self.args else "qolsys/arming"
self.qolsys_disarming_event_topic = self.args[self.__c_qolsys_disarming_topic] if self.__c_qolsys_disarming_topic in self.args else "qolsys/disarming"
self.qolsys_alarm_status_topic = self.args[self.__c_qolsys_alarm_status_topic] if self.__c_qolsys_alarm_status_topic in self.args else "qolsys/alarm/status"
self.qolsys_disarm_code = self.args[self.__c_qolsys_disarm_code__] if self.__c_qolsys_disarm_code__ in self.args else 9999
self.qolsys_confirm_disarm_code = self.args[self.__c_qolsys_confirm_disarm_code__] if self.__c_qolsys_confirm_disarm_code__ in self.args else False
self.qolsys_confirm_arm_code = self.args[self.__c_qolsys_confirm_arm_code__] if self.__c_qolsys_confirm_arm_code__ in self.args else False

self.log("qolsys_host: %s, qolsys_port: %s, qolsys_token: %s, qolsys_timeout: %s, request_topic: %s", self.qolsys_host, self.qolsys_port, self.qolsys_token, self.qolsys_timeout, self.request_topic, level="DEBUG")
self.log("Creating qolsys_socket", level="INFO")
Expand Down
2 changes: 1 addition & 1 deletion apps/ad-qolsys/qolsys_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def mqtt_info_event_received(self, event_name, data, kwargs):
partition_id = part["partition_id"]
partition_name = part["name"]
partition_status = part["status"]
this_partition = partition.partition(p_id=partition_id, name=partition_name, status=partition_status)
this_partition = partition.partition(p_id=partition_id, name=partition_name, status=partition_status, code=self.app.qolsys_disarm_code, confirm_code_arm=self.app.qolsys_confirm_arm_code, confirm_code_disarm=self.app.qolsys_confirm_disarm_code)
self.app.update_partition(partition_id, this_partition)
# self.app.call_service("mqtt/publish", namespace=self.app.mqtt_namespace, topic=this_partition.config_topic, payload=json.dumps(this_partition.config_payload()))
# self.app.call_service("mqtt/publish", namespace=self.app.mqtt_namespace, topic=this_partition.state_topic, payload=this_partition.status)
Expand Down

0 comments on commit 7b34a93

Please sign in to comment.