qolsys-controller 0.0.44__py3-none-any.whl → 0.0.62__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of qolsys-controller might be problematic. Click here for more details.

Files changed (73) hide show
  1. qolsys_controller/controller.py +829 -20
  2. qolsys_controller/database/db.py +48 -29
  3. qolsys_controller/database/table.py +89 -60
  4. qolsys_controller/database/table_alarmedsensor.py +0 -2
  5. qolsys_controller/database/table_automation.py +0 -1
  6. qolsys_controller/database/table_country_locale.py +0 -1
  7. qolsys_controller/database/table_dashboard_msgs.py +1 -2
  8. qolsys_controller/database/table_dimmerlight.py +0 -1
  9. qolsys_controller/database/table_doorlock.py +0 -1
  10. qolsys_controller/database/table_eu_event.py +1 -2
  11. qolsys_controller/database/table_heat_map.py +0 -2
  12. qolsys_controller/database/table_history.py +4 -1
  13. qolsys_controller/database/table_iqremotesettings.py +0 -2
  14. qolsys_controller/database/table_iqrouter_network_config.py +0 -1
  15. qolsys_controller/database/table_iqrouter_user_device.py +0 -2
  16. qolsys_controller/database/table_master_slave.py +0 -1
  17. qolsys_controller/database/table_nest_device.py +0 -1
  18. qolsys_controller/database/table_output_rules.py +0 -1
  19. qolsys_controller/database/table_partition.py +0 -1
  20. qolsys_controller/database/table_pgm_outputs.py +0 -2
  21. qolsys_controller/database/table_powerg_device.py +0 -2
  22. qolsys_controller/database/table_qolsyssettings.py +0 -2
  23. qolsys_controller/database/table_scene.py +0 -2
  24. qolsys_controller/database/table_sensor.py +2 -2
  25. qolsys_controller/database/table_sensor_group.py +23 -0
  26. qolsys_controller/database/table_shades.py +0 -2
  27. qolsys_controller/database/table_smartsocket.py +0 -2
  28. qolsys_controller/database/table_state.py +0 -1
  29. qolsys_controller/database/table_tcc.py +0 -1
  30. qolsys_controller/database/table_thermostat.py +0 -1
  31. qolsys_controller/database/table_trouble_conditions.py +0 -2
  32. qolsys_controller/database/table_user.py +0 -2
  33. qolsys_controller/database/table_virtual_device.py +0 -2
  34. qolsys_controller/database/table_weather.py +0 -2
  35. qolsys_controller/database/table_zigbee_device.py +0 -1
  36. qolsys_controller/database/table_zwave_association_group.py +0 -1
  37. qolsys_controller/database/table_zwave_history.py +0 -1
  38. qolsys_controller/database/table_zwave_node.py +0 -1
  39. qolsys_controller/database/table_zwave_other.py +0 -1
  40. qolsys_controller/enum.py +37 -12
  41. qolsys_controller/enum_zwave.py +81 -36
  42. qolsys_controller/errors.py +9 -12
  43. qolsys_controller/mdns.py +7 -4
  44. qolsys_controller/mqtt_command.py +119 -0
  45. qolsys_controller/mqtt_command_queue.py +5 -4
  46. qolsys_controller/observable.py +2 -2
  47. qolsys_controller/panel.py +195 -151
  48. qolsys_controller/partition.py +129 -127
  49. qolsys_controller/pki.py +69 -97
  50. qolsys_controller/scene.py +30 -28
  51. qolsys_controller/settings.py +96 -50
  52. qolsys_controller/state.py +59 -34
  53. qolsys_controller/task_manager.py +8 -12
  54. qolsys_controller/users.py +25 -0
  55. qolsys_controller/utils_mqtt.py +8 -16
  56. qolsys_controller/weather.py +71 -0
  57. qolsys_controller/zone.py +242 -214
  58. qolsys_controller/zwave_device.py +108 -95
  59. qolsys_controller/zwave_dimmer.py +53 -50
  60. qolsys_controller/zwave_garagedoor.py +0 -1
  61. qolsys_controller/zwave_generic.py +2 -3
  62. qolsys_controller/zwave_lock.py +47 -44
  63. qolsys_controller/zwave_outlet.py +0 -1
  64. qolsys_controller/zwave_thermostat.py +112 -118
  65. qolsys_controller-0.0.62.dist-info/METADATA +89 -0
  66. qolsys_controller-0.0.62.dist-info/RECORD +69 -0
  67. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.62.dist-info}/WHEEL +1 -1
  68. qolsys_controller/plugin.py +0 -34
  69. qolsys_controller/plugin_c4.py +0 -17
  70. qolsys_controller/plugin_remote.py +0 -1298
  71. qolsys_controller-0.0.44.dist-info/METADATA +0 -93
  72. qolsys_controller-0.0.44.dist-info/RECORD +0 -68
  73. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.62.dist-info}/licenses/LICENSE +0 -0
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTablePgmOutputs(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.PgmOutputsContentProvider/pgm_outputs"
@@ -15,7 +14,6 @@ class QolsysTablePgmOutputs(QolsysTable):
15
14
  self._abort_on_error = False
16
15
  self._implemented = False
17
16
 
18
-
19
17
  self._columns = [
20
18
  "_id",
21
19
  ]
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTablePowerGDevice(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.PowerGDeviceContentProvider/powerg_device"
@@ -15,7 +14,6 @@ class QolsysTablePowerGDevice(QolsysTable):
15
14
  self._abort_on_error = False
16
15
  self._implemented = True
17
16
 
18
-
19
17
  self._columns = [
20
18
  "_id",
21
19
  "avg_link_quality",
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableQolsysSettings(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.QolsysSettingsProvider/qolsyssettings"
@@ -15,7 +14,6 @@ class QolsysTableQolsysSettings(QolsysTable):
15
14
  self._abort_on_error = False
16
15
  self._implemented = True
17
16
 
18
-
19
17
  self._columns = [
20
18
  "_id",
21
19
  "version",
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableScene(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.SceneContentProvider/scene"
@@ -15,7 +14,6 @@ class QolsysTableScene(QolsysTable):
15
14
  self._abort_on_error = False
16
15
  self._implemented = True
17
16
 
18
-
19
17
  self._columns = [
20
18
  "_id",
21
19
  "version",
@@ -7,12 +7,11 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableSensor(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.SensorContentProvider/sensor"
14
13
  self._table = "sensor"
15
- self._abort_on_error = True
14
+ self._abort_on_error = False
16
15
  self._implemented = True
17
16
 
18
17
  self._columns = [
@@ -65,6 +64,7 @@ class QolsysTableSensor(QolsysTable):
65
64
  "secondary_panel_mac_address",
66
65
  "extras",
67
66
  "allowspeaker",
67
+ "firmware_version",
68
68
  ]
69
69
 
70
70
  self._create_table()
@@ -0,0 +1,23 @@
1
+ import logging # noqa: INP001
2
+ import sqlite3
3
+
4
+ from .table import QolsysTable
5
+
6
+ LOGGER = logging.getLogger(__name__)
7
+
8
+
9
+ class QolsysTableSensorGroup(QolsysTable):
10
+ def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
11
+ super().__init__(db, cursor)
12
+ self._uri = "content://com.qolsys.qolsysprovider.SensorGroupContentProvider/sensor_group" # ?
13
+ self._table = "sensor_group"
14
+ self._abort_on_error = False
15
+ self._implemented = True
16
+
17
+ self._columns = [
18
+ "_id",
19
+ "GROUPNAME",
20
+ "ACTIVEARMINGMODE",
21
+ ]
22
+
23
+ self._create_table()
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableShades(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ShadesContentProvider/shades"
@@ -20,4 +19,3 @@ class QolsysTableShades(QolsysTable):
20
19
  ]
21
20
 
22
21
  self._create_table()
23
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableSmartSocket(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.SmartSocketsContentProvider/smartsocket"
@@ -20,4 +19,3 @@ class QolsysTableSmartSocket(QolsysTable):
20
19
  ]
21
20
 
22
21
  self._create_table()
23
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableState(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.StateContentProvider/state"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableTcc(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.TccContentProvider/tcc"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableThermostat(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ThermostatsContentProvider/thermostat"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableTroubleConditions(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.TroubleConditionsContentProvider/trouble_conditions"
@@ -28,4 +27,3 @@ class QolsysTableTroubleConditions(QolsysTable):
28
27
  ]
29
28
 
30
29
  self._create_table()
31
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableUser(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.UserContentProvider/user"
@@ -43,4 +42,3 @@ class QolsysTableUser(QolsysTable):
43
42
  ]
44
43
 
45
44
  self._create_table()
46
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableVirtualDevice(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.VirtualDeviceContentProvider/virtual_device"
@@ -20,4 +19,3 @@ class QolsysTableVirtualDevice(QolsysTable):
20
19
  ]
21
20
 
22
21
  self._create_table()
23
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableWeather(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ForecastWeatherContentProvider/weather"
@@ -30,4 +29,3 @@ class QolsysTableWeather(QolsysTable):
30
29
  ]
31
30
 
32
31
  self._create_table()
33
-
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableZigbeeDevice(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ZigbeeDeviceContentProvider/zigbee_device"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableZwaveAssociationGroup(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ZwaveAssociationGroupContentProvider/zwave_association_group"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableZwaveHistory(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ZDeviceHistoryContentProvider/zwave_history"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableZwaveNode(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ZwaveContentProvider/zwave_node"
@@ -7,7 +7,6 @@ LOGGER = logging.getLogger(__name__)
7
7
 
8
8
 
9
9
  class QolsysTableZwaveOther(QolsysTable):
10
-
11
10
  def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
12
11
  super().__init__(db, cursor)
13
12
  self._uri = "content://com.qolsys.qolsysprovider.ZwaveOtherDeviceContentProvider/zwave_other"
qolsys_controller/enum.py CHANGED
@@ -12,6 +12,12 @@ class PartitionSystemStatus(StrEnum):
12
12
  UNKNOWN = "UNKNOWN"
13
13
 
14
14
 
15
+ class PartitionArmingType(StrEnum):
16
+ ARM_STAY = "ui_armstay"
17
+ ARM_AWAY = "ui_armaway"
18
+ ARM_NIGHT = "ui_armnight"
19
+
20
+
15
21
  class PartitionAlarmState(StrEnum):
16
22
  NONE = "None"
17
23
  DELAY = "Delay"
@@ -27,6 +33,18 @@ class PartitionAlarmType(StrEnum):
27
33
  SILENT_POLICE_EMERGENCY = "Silent Police Emergency"
28
34
  GLASS_BREAK_AWAY_ONLY = "glassbreakawayonly"
29
35
  GLASS_BREAK = "glassbreak"
36
+ ENTRY_EXIT_NORMAL_DELAY = "entryexitdelay"
37
+ ENTRY_EXIT_LONG_DELAY = "entryexitlongdelay"
38
+ INSTANT_PERIMETER_DW = "instantperimeter"
39
+ INSTANT_INTERIOR_DOOR = "instantinterior"
40
+ AWAY_INSTANT_FOLLOWER_DELAY = "awayinstantfollowerdelay"
41
+ REPORTING_SAFETY_SENSOR = "reportingsafety"
42
+ DELAYED_REPORTING_SAFETY_SENSOR = "delayedreportingsafety"
43
+ AWAY_INSTANT_MOTION = "awayinstantmotion"
44
+ STAY_INSTANT_MOTION = "stayinstantmotion"
45
+ STAY_DELAY_MOTION = "staydelaymotion"
46
+ AWAY_DELAY_MOTION = "awaydelaymotion"
47
+
30
48
 
31
49
  class ZoneStatus(StrEnum):
32
50
  ALARMED = "Alarmed"
@@ -43,6 +61,14 @@ class ZoneStatus(StrEnum):
43
61
  CONNECTED = "connected"
44
62
  DISCONNECTED = "disconnected"
45
63
  FAILURE = "Failure"
64
+ NOT_NETWORKED = "Not Networked"
65
+
66
+
67
+ class DeviceCapability(StrEnum):
68
+ SRF = "SRF"
69
+ WIFI = "WiFi"
70
+ POWERG = "POWERG"
71
+ ZWAVE = "Z-Wave"
46
72
 
47
73
 
48
74
  class ZoneSensorType(StrEnum):
@@ -93,19 +119,18 @@ class ZoneSensorGroup(StrEnum):
93
119
  SMOKE_HEAT = "smoke_heat"
94
120
  TAMPER_ZONE = "tamperzone"
95
121
  SHOCK = "shock"
122
+ ENTRY_EXIT_NORMAL_DELAY = "entryexitdelay"
123
+ ENTRY_EXIT_LONG_DELAY = "entryexitlongdelay"
124
+ INSTANT_PERIMETER_DW = "instantperimeter"
125
+ INSTANT_INTERIOR_DOOR = "instantinterior"
126
+ AWAY_INSTANT_FOLLOWER_DELAY = "awayinstantfollowerdelay"
127
+ REPORTING_SAFETY_SENSOR = "reportingsafety"
128
+ DELAYED_REPORTING_SAFETY_SENSOR = "delayedreportingsafety"
129
+ AWAY_INSTANT_MOTION = "awayinstantmotion"
130
+ STAY_INSTANT_MOTION = "stayinstantmotion"
131
+ STAY_DELAY_MOTION = "staydelaymotion"
132
+ AWAY_DELAY_MOTION = "awaydelaymotion"
96
133
 
97
-
98
- # ENTRY_EXIT_NORMAL_DELAY = "" #TBD
99
- # ENTRY_EXIT_LONG_DELAY = "" #TBD
100
- # INSTANT_PERIMETER_DW = "" #TBD
101
- # INSTRANT_INTERIOR_DOOR = "" #TBD
102
- # AWAY_INSTANT_FOLLOWER_DELAY = "" #TBD
103
- # REPORTING_SAFETY_SENSOR = "" #TBD
104
- # DELAYED_REPORTING_SAFETY_SENSOR = "" #TBD
105
- # AWAY_INSTANT_MOTION = "" #TBD
106
- # STAY_INSTANT_MOTION = "" #TBD
107
- # STAY_DELAY_MOTION = "" #TBD
108
- # AWAY_DELAY_MOTION = "" #TBD
109
134
  # TAKEOVER = "" #TBD
110
135
  # GARAGE_TILT_SAFETY = "" # TBD
111
136
  # WATER_SENSOR = "" # TBD
@@ -1,37 +1,82 @@
1
- from enum import Enum
2
-
3
-
4
- class ThermostatMode(Enum):
5
- OFF: 0x0001
6
- HEAT: 0x0002
7
- COOL: 0x0004
8
- AUTO: 0x0008
9
- AUX_HEAT: 0x0010
10
- RESUME: 0x0020
11
- FAN_ONLY: 0x0040
12
- FURNACE: 0x0080
13
- DRY_AIR: 0x0100
14
- MOIST_AIR: 0x0200
15
- AUTO_CHANGEOVER: 0x0400
16
- ENERGY_SAVE_HEAT: 0x0800
17
- ENERGY_SAVE_COOL: 0x1000
18
- AWAY: 0x2000
19
- FULL_POWER: 0x4000
20
- MANUFACTURER_SPECEFIC: 0x8000
21
-
22
-
23
- class ThermostatFanMode(Enum):
24
- AUTO_LOW: 0x0001
25
- LOW: 0x0002
26
- AUTO_HIGH: 0x0004
27
- HIGH: 0x0008
28
- AUTO_MEDIUM: 0x0010
29
- MEDIUM: 0x0020
30
- CIRCULATION: 0x4000
31
- HUMIDITY_CIRCULATION: 0x0080
32
- LEFT_RIGHT: 0x0100
33
- UP_DOWN: 0x0200
34
- QUIET: 0x0400
35
- EXTERNAL_CIRCULATION: 0x0800
36
- MANUFACTURER_SPECEFIC: 0x1000
1
+ from enum import Enum, IntEnum
37
2
 
3
+
4
+ class ThermostatMode(IntEnum):
5
+ OFF = 0x0001
6
+ HEAT = 0x0002
7
+ COOL = 0x0004
8
+ AUTO = 0x0008
9
+ AUX_HEAT = 0x0010
10
+ RESUME = 0x0020
11
+ FAN_ONLY = 0x0040
12
+ FURNACE = 0x0080
13
+ DRY_AIR = 0x0100
14
+ MOIST_AIR = 0x0200
15
+ AUTO_CHANGEOVER = 0x0400
16
+ ENERGY_SAVE_HEAT = 0x0800
17
+ ENERGY_SAVE_COOL = 0x1000
18
+ AWAY = 0x2000
19
+ FULL_POWER = 0x4000
20
+ MANUFACTURER_SPECEFIC = 0x8000
21
+
22
+
23
+ class ThermostatFanMode(IntEnum):
24
+ AUTO_LOW = 0x0001
25
+ LOW = 0x0002
26
+ AUTO_HIGH = 0x0004
27
+ HIGH = 0x0008
28
+ AUTO_MEDIUM = 0x0010
29
+ MEDIUM = 0x0020
30
+ CIRCULATION = 0x4000
31
+ HUMIDITY_CIRCULATION = 0x0080
32
+ LEFT_RIGHT = 0x0100
33
+ UP_DOWN = 0x0200
34
+ QUIET = 0x0400
35
+ EXTERNAL_CIRCULATION = 0x0800
36
+ MANUFACTURER_SPECEFIC = 0x1000
37
+
38
+
39
+ class ZwaveCommand(IntEnum):
40
+ SwitchBinary = 0x25
41
+ SwitchMultilevel = 0x26
42
+ ThermostatMode = 0x40
43
+ ThermostatSetPoint = 0x43
44
+ ThermostatFanMode = 0x44
45
+ ThermostatFanState = 0x45
46
+ DoorLock = 0x62
47
+
48
+
49
+ class ZwaveDeviceClass(Enum):
50
+ Unknown = 0x00
51
+ GenericController = 0x01
52
+ StaticController = 0x02
53
+ AVControlPoint = 0x03
54
+ Display = 0x04
55
+ DoorLock = 0x05
56
+ Thermostat = 0x06
57
+ SensorBinary = 0x07
58
+ SensorMultilevel = 0x08
59
+ Meter = 0x09
60
+ EntryControl = 0x0A
61
+ SemiInteroperable = 0x0B
62
+ Button = 0x0C
63
+ RepeaterSlave = 0x0F
64
+ SwitchBinary = 0x10
65
+ SwitchMultilevel = 0x11
66
+ RemoteSwitchBinary = 0x12
67
+ RemoteSwitchMultilevel = 0x13
68
+ SwitchToggleBinary = 0x14
69
+ SwitchToggleMultilevel = 0x15
70
+ ZIPNode = 0x16
71
+ Ventilation = 0x17
72
+ WindowCovering = 0x18
73
+ BarrierOperator = 0x20
74
+ SensorNotification = 0x21
75
+ SoundSwitch = 0x22
76
+ MeterPulse = 0x23
77
+ ColorSwitch = 0x24
78
+ ClimateControlSchedule = 0x25
79
+ RemoteAssociationActivator = 0x26
80
+ SceneController = 0x27
81
+ SceneSceneActuatorConfiguration = 0x28
82
+ SimpleAVControlPoint = 0x30
@@ -1,37 +1,34 @@
1
1
  import logging
2
+ from typing import Any
2
3
 
3
4
  LOGGER = logging.getLogger(__name__)
4
5
 
5
6
 
6
7
  class QolsysError(Exception):
7
-
8
- def __init__(self, *args, **kwargs) -> None:
8
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
9
9
  super().__init__(*args, **kwargs)
10
10
 
11
11
 
12
12
  class QolsysSslError(QolsysError):
13
-
14
13
  def __init__(self) -> None:
15
14
  super().__init__("QolsysSslError")
16
15
 
17
16
 
18
17
  class QolsysMqttError(QolsysError):
19
-
20
18
  def __init__(self) -> None:
21
19
  super().__init__("QolsysMqttError")
22
20
 
23
21
 
24
22
  class QolsysSqlError(QolsysError):
25
-
26
- def __init__(self, operation: dict) -> None:
23
+ def __init__(self, operation: dict[str, Any]) -> None:
27
24
  super().__init__("QolsysSqlError")
28
25
 
29
- table = f"QolsysSqlError - table:{operation.get('table', "")}"
30
- query = f"QolsysSqlError - query:{operation.get('query', "")}"
31
- columns = f"QolsysSqlError - columns:{operation.get('columns', "")}"
32
- content_values = f"QolsysSqlError - content_values:{operation.get('content_value', "")}"
33
- selection = f"QolsysSqlError - selection:{operation.get('selection', "")}"
34
- selection_argument = f"QolsysSqlError - selection_argument:{operation.get('selection_argument', "")}"
26
+ table = f"QolsysSqlError - table:{operation.get('table', '')}"
27
+ query = f"QolsysSqlError - query:{operation.get('query', '')}"
28
+ columns = f"QolsysSqlError - columns:{operation.get('columns', '')}"
29
+ content_values = f"QolsysSqlError - content_values:{operation.get('content_value', '')}"
30
+ selection = f"QolsysSqlError - selection:{operation.get('selection', '')}"
31
+ selection_argument = f"QolsysSqlError - selection_argument:{operation.get('selection_argument', '')}"
35
32
 
36
33
  e = f"""\n{table}\n{query}\n{columns}\n{content_values}\n{selection}\n{selection_argument}"""
37
34
  LOGGER.exception(e)
qolsys_controller/mdns.py CHANGED
@@ -5,10 +5,13 @@ from zeroconf.asyncio import AsyncZeroconf
5
5
 
6
6
 
7
7
  class QolsysMDNS:
8
-
9
- def __init__(self, ip: str, port: int) -> None:
10
-
11
- self.azc = AsyncZeroconf()
8
+ def __init__(self, ip: str, port: int, external_zero_conf: AsyncZeroconf | None = None) -> None:
9
+ # Add possible external zeroconf instance provided by Home Assistant by example
10
+ # If no external instance is provided, create our own
11
+ if external_zero_conf:
12
+ self.azc = external_zero_conf
13
+ else:
14
+ self.azc = AsyncZeroconf()
12
15
 
13
16
  self.mdns_info = ServiceInfo(
14
17
  "_http._tcp.local.",
@@ -0,0 +1,119 @@
1
+ import json
2
+ import logging
3
+ import uuid
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ from .errors import QolsysMqttError
7
+
8
+ if TYPE_CHECKING:
9
+ import aiomqtt
10
+
11
+ from .controller import QolsysController
12
+
13
+ LOGGER = logging.getLogger(__name__)
14
+
15
+
16
+ class MQTTCommand:
17
+ def __init__(
18
+ self,
19
+ controller: "QolsysController",
20
+ eventName: str,
21
+ ) -> None:
22
+ self._controller: QolsysController = controller
23
+ self._client: aiomqtt.Client | None = controller.aiomqtt
24
+ self._topic: str = "mastermeid"
25
+ self._eventName: str = eventName
26
+ self._payload: dict[str, Any] = {}
27
+ self._requestID = str(uuid.uuid4())
28
+ self._qos: int = self._controller.settings.mqtt_qos
29
+ self._responseTopic = "response_" + self._controller.settings.random_mac
30
+
31
+ self.append("requestID", self._requestID)
32
+ self.append("responseTopic", self._responseTopic)
33
+ self.append("eventName", self._eventName)
34
+ self.append("remoteMacAddress", self._controller.settings.random_mac)
35
+
36
+ def append(self, argument: str, value: str | dict[str, Any] | int | bool | list[dict[str, Any]] | Any) -> None:
37
+ self._payload[argument] = value
38
+
39
+ async def send_command(self) -> dict[str, Any]:
40
+ if self._client is None:
41
+ LOGGER.error("MQTT Client not configured")
42
+ raise QolsysMqttError
43
+
44
+ await self._client.publish(topic=self._topic, payload=json.dumps(self._payload), qos=self._qos)
45
+ return await self._controller.mqtt_command_queue.wait_for_response(self._requestID)
46
+
47
+
48
+ class MQTTCommand_IpcCall(MQTTCommand):
49
+ def __init__(
50
+ self,
51
+ controller: "QolsysController",
52
+ ipc_service_name: str,
53
+ ipc_interface_name: str,
54
+ ipc_transaction_id: int,
55
+ ) -> None:
56
+ super().__init__(controller, "ipcCall")
57
+ self.append("ipcServiceName", ipc_service_name)
58
+ self.append("ipcInterfaceName", ipc_interface_name)
59
+ self.append("ipcTransactionID", ipc_transaction_id)
60
+
61
+ def append_ipc_request(self, ipc_request: list[dict[str, Any]]) -> None:
62
+ self.append("ipcRequest", ipc_request)
63
+
64
+
65
+ class MQTTCommand_Panel(MQTTCommand_IpcCall):
66
+ def __init__(
67
+ self,
68
+ controller: "QolsysController",
69
+ ) -> None:
70
+ super().__init__(
71
+ controller=controller,
72
+ ipc_service_name="qinternalservice",
73
+ ipc_interface_name="android.os.IQInternalService",
74
+ ipc_transaction_id=7,
75
+ )
76
+
77
+
78
+ class MQTTCommand_ZWave(MQTTCommand_IpcCall):
79
+ def __init__(
80
+ self,
81
+ controller: "QolsysController",
82
+ node_id: str,
83
+ zwave_command: list[int],
84
+ ) -> None:
85
+ super().__init__(
86
+ controller=controller,
87
+ ipc_service_name="qzwaveservice",
88
+ ipc_interface_name="android.os.IQZwaveService",
89
+ ipc_transaction_id=47,
90
+ )
91
+
92
+ ipc_request: list[dict[str, Any]] = [
93
+ {
94
+ "dataType": "int",
95
+ "dataValue": int(node_id),
96
+ },
97
+ {
98
+ "dataType": "int",
99
+ "dataValue": 0,
100
+ },
101
+ {
102
+ "dataType": "byteArray",
103
+ "dataValue": zwave_command,
104
+ },
105
+ {
106
+ "dataType": "int",
107
+ "dataValue": 0,
108
+ },
109
+ {
110
+ "dataType": "int",
111
+ "dataValue": 106,
112
+ },
113
+ {
114
+ "dataType": "byteArray",
115
+ "dataValue": [0],
116
+ },
117
+ ]
118
+
119
+ self.append_ipc_request(ipc_request)
@@ -1,12 +1,13 @@
1
1
  import asyncio
2
+ from typing import Any
2
3
 
3
4
 
4
5
  class QolsysMqttCommandQueue:
5
6
  def __init__(self) -> None:
6
7
  self.lock = asyncio.Lock()
7
- self.waiters: dict[str, asyncio.Future] = {}
8
+ self.waiters: dict[str, asyncio.Future[Any]] = {}
8
9
 
9
- async def handle_response(self, response: dict) -> None:
10
+ async def handle_response(self, response: dict[str, str]) -> None:
10
11
  requestID = response.get("requestID")
11
12
 
12
13
  if not requestID:
@@ -19,7 +20,7 @@ class QolsysMqttCommandQueue:
19
20
  if future and not future.done():
20
21
  future.set_result(response)
21
22
 
22
- async def wait_for_response(self, request_id: str) -> None:
23
+ async def wait_for_response(self, request_id: str) -> dict[str, Any]:
23
24
  if request_id in self.waiters:
24
25
  msg = f"Duplicate waiter for request_id: {request_id}"
25
26
  raise ValueError(msg)
@@ -28,4 +29,4 @@ class QolsysMqttCommandQueue:
28
29
  async with self.lock:
29
30
  self.waiters[request_id] = future
30
31
 
31
- return await future
32
+ return await future # type: ignore[no-any-return]