From 1e9441a4ba4caaafda247dbe6a81622b5af720a2 Mon Sep 17 00:00:00 2001 From: JeromeHXP Date: Thu, 7 Mar 2024 08:13:36 +0100 Subject: [PATCH 1/5] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6cd6f0b..35e6d23 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ ], python_requires='>=3.6', install_requires=[ - 'cryptograpy>=3.1' + 'cryptography>=3.1' ] ) From 66f92d1f2e799445282611da60e71d4799867618 Mon Sep 17 00:00:00 2001 From: dridi14 Date: Mon, 1 Apr 2024 23:27:33 +0200 Subject: [PATCH 2/5] IBSP-4201 fix qualifier error --- dc09_spt/msg/dc05_msg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dc09_spt/msg/dc05_msg.py b/dc09_spt/msg/dc05_msg.py index 436adbe..8d0f040 100644 --- a/dc09_spt/msg/dc05_msg.py +++ b/dc09_spt/msg/dc05_msg.py @@ -82,7 +82,7 @@ def dc05event(spt_account, params={}): if len(code) != 3: raise Exception('Code should be 3 positions') q = param.numpar(params, 'q', '1') - if q != '1' and q != '3' and q != '3': + if q not in ['1', '3', '6']: raise Exception('Qualifier q should be 1 or 3 or 6') area = param.numpar(params, 'area', '00') if len(area) != 2: From 5872e1ec2b547229f52853f05a97854152de0a6f Mon Sep 17 00:00:00 2001 From: dridi14 Date: Tue, 23 Apr 2024 12:29:21 +0200 Subject: [PATCH 3/5] IBSP-4201 Add support for 'CONTACT-ID' message type in dc09_spt.py --- dc09_spt/dc09_spt.py | 4 +++ dc09_spt/msg/dc05_msg.py | 57 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/dc09_spt/dc09_spt.py b/dc09_spt/dc09_spt.py index 7a22bb2..b017e83 100644 --- a/dc09_spt/dc09_spt.py +++ b/dc09_spt/dc09_spt.py @@ -236,6 +236,7 @@ def send_msg(self, mtype, mparam): current implemented is : 'SIA' or 'SIA-DCS' for sending a message with a SIA-DC03 payload 'CID' or 'ADM-CID' for sending a message with a SIA-DC05 payload + 'CONTACT-ID' for sending a message with a SIA-DC05 payload mparam a map of key value pairs defining the message content. for a description of possible values see the documentation of the payload @@ -257,6 +258,9 @@ def send_msg(self, mtype, mparam): if mtype == 'CID' or mtype == 'ADM-CID': msg = dc05_msg.dc05event(self.account, mparam) dc09type = 'ADM-CID' + if mtype == 'CONTACT-ID': + msg = dc05_msg.conactid2dc05(self.account, mparam) + dc09type = 'ADM-CID' extra = dc09_msg.dc09_extra(mparam) if extra is not None: msg = msg + extra diff --git a/dc09_spt/msg/dc05_msg.py b/dc09_spt/msg/dc05_msg.py index 8d0f040..727b7b9 100644 --- a/dc09_spt/msg/dc05_msg.py +++ b/dc09_spt/msg/dc05_msg.py @@ -96,3 +96,60 @@ def dc05event(spt_account, params={}): zone = ('000' + zone)[-3:] msg += q + code + ' ' + area + ' ' + zone + ']' return msg + + @staticmethod + def conactid2dc05(spt_account, params={}): + """ + Construct a DC05 message, also called Ademco Contact ID + Parameters + spt_account + the account of the alarm transceiver. + in most situations this will be used in the alarm message too, but for situations like + a cloud based receiver, the account in the map will be different. + params + a map with key-value pairs. + at this moment only the more commonly used fields are used. + the currently handled keys are: + account + the account number. + most receivers expect 4 to 8 numeric digits + area + the area number in which the event happened + (area is a part of an installation that can arm and disarm independently) + zone + the alarm zone. + code + the event code in 3 numbers according to the DC05 standard. + q + the qualifier defining the state of the alarm. + 1 means new alarm + 3 means new restore + 6 means old alarm + """ + account = param.strpar(params, 'account', spt_account) + zone = param.numpar(params, 'zone', '000') + area = param.numpar(params, 'area', '00') + qualifier = param.numpar(params, 'q', '1') + event_code = param.numpar(params, 'code', '602') + + if len(event_code) != 3: + raise ValueError("Event code should be 3 digits") + + if qualifier not in ['1', '3']: + raise ValueError("Qualifier should be 1 (new event) or 3 (restore)") + + qualifier_code = qualifier + event_code + + parts = [account, '18', qualifier_code, area, zone] + + # Calculate checksum + checksum = self.calculate_checksum(parts) + total = sum(int(digit) if digit != '0' else 10 for part in parts for digit in part) + next_multiple = ((total // 15) + 1) * 15 + checksum = next_multiple - total if checksum != 0 else 'F' + + # Complete message with checksum + complete_message = ' '.join(parts) + ' ' + str(checksum) + return complete_message + + From 99668c1eb74ff729b87f730488f6f84576a8736e Mon Sep 17 00:00:00 2001 From: dridi14 Date: Tue, 23 Apr 2024 12:51:12 +0200 Subject: [PATCH 4/5] fix checksum --- dc09_spt/msg/dc05_msg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dc09_spt/msg/dc05_msg.py b/dc09_spt/msg/dc05_msg.py index 727b7b9..5e2b64e 100644 --- a/dc09_spt/msg/dc05_msg.py +++ b/dc09_spt/msg/dc05_msg.py @@ -143,10 +143,10 @@ def conactid2dc05(spt_account, params={}): parts = [account, '18', qualifier_code, area, zone] # Calculate checksum - checksum = self.calculate_checksum(parts) total = sum(int(digit) if digit != '0' else 10 for part in parts for digit in part) next_multiple = ((total // 15) + 1) * 15 - checksum = next_multiple - total if checksum != 0 else 'F' + checksum = next_multiple - total + checksum = checksum if checksum != 0 else 'F' # Complete message with checksum complete_message = ' '.join(parts) + ' ' + str(checksum) From 748a6f3bc82285457f652ce5ca29e3af7aba0cef Mon Sep 17 00:00:00 2001 From: dridi14 Date: Tue, 23 Apr 2024 12:58:21 +0200 Subject: [PATCH 5/5] add missing ] --- dc09_spt/msg/dc05_msg.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dc09_spt/msg/dc05_msg.py b/dc09_spt/msg/dc05_msg.py index 5e2b64e..720a53a 100644 --- a/dc09_spt/msg/dc05_msg.py +++ b/dc09_spt/msg/dc05_msg.py @@ -135,8 +135,8 @@ def conactid2dc05(spt_account, params={}): if len(event_code) != 3: raise ValueError("Event code should be 3 digits") - if qualifier not in ['1', '3']: - raise ValueError("Qualifier should be 1 (new event) or 3 (restore)") + if qualifier not in ['1', '3', '6']: + raise ValueError("Qualifier should be 1 (new event) or 3 (restore) or 6 (old event)") qualifier_code = qualifier + event_code @@ -149,7 +149,7 @@ def conactid2dc05(spt_account, params={}): checksum = checksum if checksum != 0 else 'F' # Complete message with checksum - complete_message = ' '.join(parts) + ' ' + str(checksum) + complete_message = ' '.join(parts) + ' ' + str(checksum) + ']' return complete_message