qolsys-controller 0.0.40__py3-none-any.whl → 0.0.51__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.

@@ -1,5 +1,10 @@
1
1
  #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
2
4
  import logging
5
+ from typing import TYPE_CHECKING
6
+
7
+ from qolsys_controller.plugin import QolsysPlugin
3
8
 
4
9
  from .panel import QolsysPanel
5
10
  from .plugin_c4 import QolsysPluginC4
@@ -9,20 +14,27 @@ from .state import QolsysState
9
14
 
10
15
  LOGGER = logging.getLogger(__name__)
11
16
 
17
+ if TYPE_CHECKING:
18
+ from .plugin import QolsysPlugin
19
+
12
20
  class QolsysController:
13
21
 
14
22
  def __init__(self) -> None:
15
23
 
16
24
  # QolsysController Information
17
- self.plugin = None
18
- self._state = QolsysState()
19
- self._settings = QolsysSettings()
20
- self._panel = QolsysPanel(settings=self.settings, state=self.state)
25
+ self._plugin: QolsysPlugin | None = None
26
+ self._state = QolsysState(self)
27
+ self._settings = QolsysSettings(self)
28
+ self._panel = QolsysPanel(self)
21
29
 
22
30
  @property
23
31
  def state(self) -> QolsysState:
24
32
  return self._state
25
33
 
34
+ @property
35
+ def plugin(self) -> QolsysPlugin:
36
+ return self._plugin
37
+
26
38
  @property
27
39
  def panel(self) -> QolsysPanel:
28
40
  return self._panel
@@ -37,13 +49,13 @@ class QolsysController:
37
49
 
38
50
  case "c4":
39
51
  LOGGER.debug("C4 Plugin Selected")
40
- self.plugin = QolsysPluginC4(self.state, self.panel, self.settings)
52
+ self._plugin = QolsysPluginC4(self)
41
53
  return
42
54
 
43
55
  case "remote":
44
56
  LOGGER.debug("Remote Plugin Selected")
45
- self.plugin = QolsysPluginRemote(self.state, self.panel, self.settings)
57
+ self._plugin = QolsysPluginRemote(self)
46
58
  return
47
59
 
48
60
  case _:
49
- LOGGER.debug("Unknow Plugin Selected")
61
+ LOGGER.error("Unknow Plugin Selected")
@@ -237,6 +237,37 @@ class QolsysDB:
237
237
 
238
238
  return zones
239
239
 
240
+ def get_weather(self) -> list[dict]:
241
+ self.cursor.execute(f"SELECT * FROM {self.table_weather.table} ORDER BY _id")
242
+ self.db.commit()
243
+
244
+ weather_list = []
245
+ columns = [description[0] for description in self.cursor.description]
246
+ for row in self.cursor.fetchall():
247
+ row_dict = dict(zip(columns, row, strict=True))
248
+ weather_list.append(row_dict)
249
+
250
+ return weather_list
251
+
252
+ def get_powerg(self, short_id: str) -> dict:
253
+ try:
254
+ self.cursor.execute(f"SELECT * FROM {self.table_powerg_device.table} WHERE shortID = ?",(short_id,))
255
+ self.db.commit()
256
+
257
+ row = self.cursor.fetchone()
258
+
259
+ if row is None:
260
+ LOGGER.debug("%s value not found", short_id)
261
+ return None
262
+
263
+ columns = [description[0] for description in self.cursor.description]
264
+ return dict(zip(columns, row, strict=True))
265
+
266
+ except sqlite3.Error:
267
+ LOGGER.exception("Error getting PowerG device info for shortID %s", short_id)
268
+ return None
269
+
270
+
240
271
  def get_setting_panel(self, setting: str) -> str:
241
272
  self.cursor.execute(f"""SELECT value FROM {self.table_qolsyssettings.table}
242
273
  WHERE name = ? and partition_id = ? """, (setting, "0"))
@@ -68,6 +68,7 @@ class QolsysTable:
68
68
  raise error from err
69
69
 
70
70
  def insert(self, data: dict) -> None:
71
+
71
72
  try:
72
73
  if not self._implemented and data is not None:
73
74
  LOGGER.warning("New Table format: %s", self.uri)
@@ -92,6 +93,7 @@ class QolsysTable:
92
93
 
93
94
  col_str = ", ".join(full_data.keys())
94
95
  placeholder_str = ", ".join([f":{key}" for key in full_data])
96
+
95
97
  query = f"INSERT OR IGNORE INTO {self.table} ({col_str}) VALUES ({placeholder_str})"
96
98
  self._cursor.execute(query, full_data)
97
99
  self._db.commit()
@@ -112,9 +114,14 @@ class QolsysTable:
112
114
  # selection_argument:
113
115
  # Firmware 4.4.1: selection_argument: '[3,1]'
114
116
  # Firmware 4.6.1: selection_argument: ['3','1']
115
-
116
117
  # contentValues:{"partition_id":"0","sensorgroup":"safetymotion","sensorstatus":"Idle"}"
117
118
 
119
+ if selection_argument == "":
120
+ LOGGER.debug("Update called with empty selection_argument")
121
+ LOGGER.debug("Table: %s", self.table)
122
+ LOGGER.debug("Selection: %s", selection)
123
+ LOGGER.debug("selection_argument: %s", selection_argument)
124
+ return
118
125
 
119
126
  # Selection Argument
120
127
  # Panel send selection_argument as list in Firmware 4.6.1
@@ -164,6 +171,14 @@ class QolsysTable:
164
171
  # Firmware 4.4.1: selection_argument: '[3,1]'
165
172
  # Firmware 4.6.1: selection_argument: ['3','1']
166
173
 
174
+
175
+ if selection_argument == "":
176
+ LOGGER.debug("Delete called with empty selection_argument")
177
+ LOGGER.debug("Table: %s", self.table)
178
+ LOGGER.debug("Selection: %s", selection)
179
+ LOGGER.debug("selection_argument: %s", selection_argument)
180
+ return
181
+
167
182
  # Selection Argument
168
183
  if(type(selection_argument) is not list):
169
184
  #Firmware 4.4.1, seletion_argument is sent as a string
@@ -13,7 +13,7 @@ class QolsysTablePowerGDevice(QolsysTable):
13
13
  self._uri = "content://com.qolsys.qolsysprovider.PowerGDeviceContentProvider/powerg_device"
14
14
  self._table = "powerg_device"
15
15
  self._abort_on_error = False
16
- self._implemented = False
16
+ self._implemented = True
17
17
 
18
18
 
19
19
  self._columns = [
qolsys_controller/enum.py CHANGED
@@ -94,7 +94,6 @@ class ZoneSensorGroup(StrEnum):
94
94
  TAMPER_ZONE = "tamperzone"
95
95
  SHOCK = "shock"
96
96
 
97
-
98
97
  # ENTRY_EXIT_NORMAL_DELAY = "" #TBD
99
98
  # ENTRY_EXIT_LONG_DELAY = "" #TBD
100
99
  # INSTANT_PERIMETER_DW = "" #TBD
@@ -34,4 +34,3 @@ class ThermostatFanMode(Enum):
34
34
  QUIET: 0x0400
35
35
  EXTERNAL_CIRCULATION: 0x0800
36
36
  MANUFACTURER_SPECEFIC: 0x1000
37
-
qolsys_controller/mdns.py CHANGED
@@ -6,9 +6,14 @@ from zeroconf.asyncio import AsyncZeroconf
6
6
 
7
7
  class QolsysMDNS:
8
8
 
9
- def __init__(self, ip: str, port: int) -> None:
10
-
11
- self.azc = AsyncZeroconf()
9
+ def __init__(self, ip: str, port: int, external_zero_conf: AsyncZeroconf | None = None) -> None:
10
+
11
+ # Add possible external zeroconf instance provided by Home Assistant by example
12
+ # If no external instance is provided, create our own
13
+ if external_zero_conf:
14
+ self.azc = external_zero_conf
15
+ else:
16
+ self.azc = AsyncZeroconf()
12
17
 
13
18
  self.mdns_info = ServiceInfo(
14
19
  "_http._tcp.local.",
@@ -1,5 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  import json
2
4
  import logging
5
+ from typing import TYPE_CHECKING
3
6
 
4
7
  from .database.db import QolsysDB
5
8
  from .enum import (
@@ -10,10 +13,8 @@ from .enum import (
10
13
  from .observable import QolsysObservable
11
14
  from .partition import QolsysPartition
12
15
  from .scene import QolsysScene
13
- from .settings import QolsysSettings
14
- from .state import QolsysState
16
+ from .weather import QolsysForecast, QolsysWeather
15
17
  from .zone import QolsysZone
16
- from .zwave_device import QolsysZWaveDevice
17
18
  from .zwave_dimmer import QolsysDimmer
18
19
  from .zwave_generic import QolsysGeneric
19
20
  from .zwave_lock import QolsysLock
@@ -21,12 +22,15 @@ from .zwave_thermostat import QolsysThermostat
21
22
 
22
23
  LOGGER = logging.getLogger(__name__)
23
24
 
25
+ if TYPE_CHECKING:
26
+ from .controller import QolsysController
27
+ from .zwave_device import QolsysZWaveDevice
28
+
24
29
 
25
30
  class QolsysPanel(QolsysObservable):
26
- def __init__(self, settings: QolsysSettings, state: QolsysState) -> None:
31
+ def __init__(self, controller: QolsysController) -> None:
27
32
 
28
- self._state = state
29
- self._settings = settings
33
+ self._controller = controller
30
34
  self._db = QolsysDB()
31
35
 
32
36
  # Partition settings
@@ -95,9 +99,9 @@ class QolsysPanel(QolsysObservable):
95
99
 
96
100
  def read_users_file(self) -> bool:
97
101
  # Loading user_code data from users.conf file if exists
98
- if self._settings.users_file_path.is_file():
102
+ if self._controller.settings.users_file_path.is_file():
99
103
  try:
100
- path = self._settings.users_file_path
104
+ path = self._controller.settings.users_file_path
101
105
  with path.open("r", encoding="utf-8") as file:
102
106
  try:
103
107
  users = json.load(file)
@@ -344,10 +348,12 @@ class QolsysPanel(QolsysObservable):
344
348
 
345
349
  def load_database(self, database: dict) -> None:
346
350
  self.db.load_db(database)
347
- self._state.sync_partitions_data(self.get_partitions_from_db())
348
- self._state.sync_zones_data(self.get_zones_from_db())
349
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
350
- self._state.sync_scenes_data(self.get_scenes_from_db())
351
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
352
+ self._controller.state.sync_zones_data(self.get_zones_from_db())
353
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
354
+ self._controller.state.sync_scenes_data(self.get_scenes_from_db())
355
+ self._controller.state.sync_weather_data(self.get_weather_from_db())
356
+
351
357
 
352
358
  # Parse panel update to database
353
359
  def parse_iq2meid_message(self, data: dict) -> bool: # noqa: C901, PLR0912, PLR0915
@@ -369,9 +375,13 @@ class QolsysPanel(QolsysObservable):
369
375
  match dbOperation:
370
376
 
371
377
  case "update":
372
- content_values = data.get("contentValues")
373
- selection = data.get("selection")
374
- selection_argument = data.get("selectionArgs")
378
+ content_values = data.get("contentValues","")
379
+ selection = data.get("selection","")
380
+ selection_argument = data.get("selectionArgs","")
381
+
382
+ if selection_argument == "" or selection == "":
383
+ LOGGER.debug("iq2meid invalid update selection or selectionArgs")
384
+ LOGGER.debug("data:%s", data)
375
385
 
376
386
  match uri:
377
387
 
@@ -390,7 +400,7 @@ class QolsysPanel(QolsysObservable):
390
400
  # Update Partition setting - Send notification if setting has changed
391
401
  if name in self.settings_partition:
392
402
  partition_id = content_values.get("partition_id", "")
393
- partition = self._state.partition(partition_id)
403
+ partition = self._controller.state.partition(partition_id)
394
404
  if partition is not None:
395
405
  match name:
396
406
  case "SYSTEM_STATUS":
@@ -406,7 +416,7 @@ class QolsysPanel(QolsysObservable):
406
416
  case self.db.table_sensor.uri:
407
417
  self.db.table_sensor.update(selection, selection_argument, content_values)
408
418
  zoneid = content_values.get("zoneid", "")
409
- zone = self._state.zone(zoneid)
419
+ zone = self._controller.state.zone(zone_id=zoneid)
410
420
  if zone is not None:
411
421
  zone.update(content_values)
412
422
 
@@ -418,7 +428,7 @@ class QolsysPanel(QolsysObservable):
418
428
  self.db.table_state.update(selection, selection_argument, content_values)
419
429
 
420
430
  if name in self.state_partition:
421
- partition = self._state.partition(partition_id)
431
+ partition = self._controller.state.partition(partition_id)
422
432
  if partition is not None:
423
433
  match name:
424
434
  case "ALARM_STATE":
@@ -443,7 +453,7 @@ class QolsysPanel(QolsysObservable):
443
453
  case self.db.table_partition.uri:
444
454
  self.db.table_partition.update(selection, selection_argument, content_values)
445
455
  partition_id = content_values.get("partition_id", "")
446
- partition = self._state.partition(partition_id)
456
+ partition = self._controller.state.partition(partition_id)
447
457
  if partition is not None:
448
458
  partition.update_partition(content_values)
449
459
 
@@ -456,7 +466,7 @@ class QolsysPanel(QolsysObservable):
456
466
  case self.db.table_dimmer.uri:
457
467
  self.db.table_dimmer.update(selection, selection_argument, content_values)
458
468
  node_id = content_values.get("node_id", "")
459
- node = self._state.zwave_device(node_id)
469
+ node = self._controller.state.zwave_device(node_id)
460
470
  if node is not None and isinstance(node, QolsysDimmer):
461
471
  node.update_dimmer(content_values)
462
472
 
@@ -464,7 +474,7 @@ class QolsysPanel(QolsysObservable):
464
474
  case self.db.table_thermostat.uri:
465
475
  self.db.table_thermostat.update(selection, selection_argument, content_values)
466
476
  node_id = content_values.get("node_id", "")
467
- node = self._state.zwave_device(node_id)
477
+ node = self._controller.state.zwave_device(node_id)
468
478
  if node is not None and isinstance(node, QolsysThermostat):
469
479
  node.update_thermostat(content_values)
470
480
 
@@ -472,7 +482,7 @@ class QolsysPanel(QolsysObservable):
472
482
  case self.db.table_doorlock.uri:
473
483
  self.db.table_doorlock.update(selection, selection_argument, content_values)
474
484
  node_id = content_values.get("node_id", "")
475
- node = self._state.zwave_device(node_id)
485
+ node = self._controller.state.zwave_device(node_id)
476
486
  if node is not None and isinstance(node, QolsysLock):
477
487
  node.update_lock(content_values)
478
488
 
@@ -480,7 +490,7 @@ class QolsysPanel(QolsysObservable):
480
490
  case self.db.table_zwave_node.uri:
481
491
  self.db.table_zwave_node.update(selection, selection_argument, content_values)
482
492
  node_id = content_values.get("node_id", "")
483
- node = self._state.zwave_device(node_id)
493
+ node = self._controller.state.zwave_device(node_id)
484
494
  if node is not None:
485
495
  node.update_base(content_values)
486
496
 
@@ -507,35 +517,51 @@ class QolsysPanel(QolsysObservable):
507
517
  case self.db.table_scene.uri:
508
518
  self.db.table_scene.update(selection, selection_argument, content_values)
509
519
  scene_id = content_values.get("scene_id", "")
510
- scene = self._state.scene(scene_id)
520
+ scene = self._controller.state.scene(scene_id)
511
521
  if scene is not None and isinstance(node, QolsysScene):
512
522
  scene.update(content_values)
513
523
 
514
524
  # Update Trouble Conditions
515
- case self.db.table_trouble_conditions:
525
+ case self.db.table_trouble_conditions.uri:
516
526
  self.db.table_trouble_conditions.update(selection,selection_argument,content_values)
517
527
  # No action needed
518
528
 
519
529
  # Update EU_EVENT:
520
- case self.db.table_eu_event:
530
+ case self.db.table_eu_event.uri:
521
531
  self.db.table_eu_event.update(selection,selection_argument,content_values)
522
532
  # No action needed
523
533
 
534
+ # Update PowerG Device
535
+ case self.db.table_powerg_device.uri:
536
+ self.db.table_powerg_device.update(selection,selection_argument,content_values)
537
+ short_id = content_values.get("shortID", "")
538
+ zone = self._controller.state.zone_from_short_id(short_id)
539
+ if zone is not None:
540
+ LOGGER.debug("iq2meid updating powerg device for zoneid(%s):%s", zone.zone_id,content_values)
541
+ zone.update_powerg(content_values)
524
542
 
543
+ # Update Weather
544
+ case self.db.table_weather.uri:
545
+ self.db.table_weather.update(selection,selection_argument,content_values)
546
+ self._controller.state.sync_weather_data(self.get_weather_from_db())
525
547
 
526
548
  case _:
527
549
  LOGGER.debug("iq2meid updating unknow uri:%s", uri)
528
550
  LOGGER.debug(data)
529
551
 
530
552
  case "delete":
531
- selection = data.get("selection")
532
- selection_argument = data.get("selectionArgs")
553
+ selection = data.get("selection","")
554
+ selection_argument = data.get("selectionArgs","")
555
+
556
+ if selection_argument == "" or selection == "":
557
+ LOGGER.debug("iq2meid invalid delete selection or selectionArgs")
558
+ LOGGER.debug("data:%s", data)
533
559
 
534
560
  match uri:
535
561
 
536
562
  case self.db.table_sensor.uri:
537
563
  self.db.table_sensor.delete(selection, selection_argument)
538
- self._state.sync_zones_data(self.get_zones_from_db())
564
+ self._controller.state.sync_zones_data(self.get_zones_from_db())
539
565
  # Notify delete zone
540
566
 
541
567
  case self.db.table_iqremotesettings.uri:
@@ -556,7 +582,7 @@ class QolsysPanel(QolsysObservable):
556
582
 
557
583
  case self.db.table_alarmedsensor.uri:
558
584
  self.db.table_alarmedsensor.delete(selection, selection_argument)
559
- self._state.sync_partitions_data(self.get_partitions_from_db())
585
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
560
586
 
561
587
  case self.db.table_history.uri:
562
588
  self.db.table_history.delete(selection, selection_argument)
@@ -568,19 +594,19 @@ class QolsysPanel(QolsysObservable):
568
594
 
569
595
  case self.db.table_doorlock.uri:
570
596
  self.db.table_doorlock.delete(selection, selection_argument)
571
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
597
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
572
598
 
573
599
  case self.db.table_dimmer.uri:
574
600
  self.db.table_dimmer.delete(selection, selection_argument)
575
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
601
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
576
602
 
577
603
  case self.db.table_thermostat.uri:
578
604
  self.db.table_thermostat.delete(selection, selection_argument)
579
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
605
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
580
606
 
581
607
  case self.db.table_zwave_node.uri:
582
608
  self.db.table_zwave_node.delete(selection, selection_argument)
583
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
609
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
584
610
 
585
611
  case self.db.table_automation.uri:
586
612
  self.db.table_automation.delete(selection, selection_argument)
@@ -588,7 +614,7 @@ class QolsysPanel(QolsysObservable):
588
614
 
589
615
  case self.db.table_partition.uri:
590
616
  self.db.table_partition.delete(selection, selection_argument)
591
- self._state.sync_partitions_data(self.get_partitions_from_db())
617
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
592
618
 
593
619
  case self.db.table_user.uri:
594
620
  self.db.table_user.delete(selection, selection_argument)
@@ -598,9 +624,16 @@ class QolsysPanel(QolsysObservable):
598
624
  self.db.table_dashboard_msgs.delete(selection, selection_argument)
599
625
  # No action needed
600
626
 
601
- case self.db.table_eu_event:
627
+ case self.db.table_eu_event.uri:
602
628
  self.db.table_eu_event.delete(selection,selection_argument)
603
629
 
630
+ case self.db.table_powerg_device.uri:
631
+ self.db.table_powerg_device.delete(selection,selection_argument)
632
+
633
+ case self.db.table_weather.uri:
634
+ self.db.table_weather.delete(selection,selection_argument)
635
+ self._controller.state.sync_weather_data(self.get_weather_from_db())
636
+
604
637
  case _:
605
638
  LOGGER.debug("iq2meid deleting unknown uri:%s", uri)
606
639
  LOGGER.debug(data)
@@ -618,16 +651,16 @@ class QolsysPanel(QolsysObservable):
618
651
  new_value = content_values.get("value", "")
619
652
  if name in self.state_partition:
620
653
  partition_id = content_values.get("partition_id", "")
621
- partition = self._state.partition(partition_id)
654
+ partition = self._controller.state.partition(partition_id)
622
655
  if partition is not None:
623
656
  match name:
624
657
  case "ALARM_STATE":
625
658
  partition.alarm_state = PartitionAlarmState(new_value)
626
659
 
627
660
  # Inser Partition Content Provider
628
- case self.db.table_partition:
661
+ case self.db.table_partition.uri:
629
662
  self.db.table_partition.insert(data=content_values)
630
- self._state.sync_partitions_data(self.get_partitions_from_db())
663
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
631
664
 
632
665
  # Insert Settings Content Provider
633
666
  case self.db.table_qolsyssettings.uri:
@@ -638,7 +671,7 @@ class QolsysPanel(QolsysObservable):
638
671
  new_value = content_values.get("value", "")
639
672
  if name in self.settings_partition:
640
673
  partition_id = content_values.get("partition_id", "")
641
- partition = self._state.partition(partition_id)
674
+ partition = self._controller.state.partition(partition_id)
642
675
  if partition is not None:
643
676
  match name:
644
677
  case "SYSTEM_STATUS":
@@ -668,27 +701,27 @@ class QolsysPanel(QolsysObservable):
668
701
  # Sensor Content Provider
669
702
  case self.db.table_sensor.uri:
670
703
  self.db.table_sensor.insert(data=content_values)
671
- self._state.sync_zones_data(self.get_zones_from_db())
704
+ self._controller.state.sync_zones_data(self.get_zones_from_db())
672
705
 
673
706
  # Door Lock Content Provider
674
707
  case self.db.table_doorlock.uri:
675
708
  self.db.table_doorlock.insert(data=content_values)
676
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
709
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
677
710
 
678
711
  # Dimmer Content Provider
679
712
  case self.db.table_dimmer.uri:
680
713
  self.db.table_dimmer.insert(data=content_values)
681
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
714
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
682
715
 
683
716
  # Thermostat Content Provider
684
717
  case self.db.table_thermostat.uri:
685
718
  self.db.table_thermostat.insert(data=content_values)
686
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
719
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
687
720
 
688
721
  # ZWave Node Content Provider
689
722
  case self.db.table_zwave_node.uri:
690
723
  self.db.table_zwave_node.insert(data=content_values)
691
- self._state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
724
+ self._controller.state.sync_zwave_devices_data(self.get_zwave_devices_from_db())
692
725
 
693
726
  # HistoryContentProvider
694
727
  case self.db.table_history.uri:
@@ -701,7 +734,7 @@ class QolsysPanel(QolsysObservable):
701
734
  partition_id = content_values.get("partition_id", "")
702
735
  self.db.table_alarmedsensor.insert(data=content_values)
703
736
 
704
- partition = self._state.partition(partition_id)
737
+ partition = self._controller.state.partition(partition_id)
705
738
  if partition is not None:
706
739
  partition.append_alarm_type([PartitionAlarmType(content_values.get("sgroup", ""))])
707
740
 
@@ -726,9 +759,18 @@ class QolsysPanel(QolsysObservable):
726
759
  # No action needed
727
760
 
728
761
  # EU_EVENT
729
- case self.db.table_eu_event:
762
+ case self.db.table_eu_event.uri:
730
763
  self.db.table_eu_event.insert(data=content_values)
731
764
 
765
+ # PowerG Device
766
+ case self.db.table_powerg_device.uri:
767
+ self.db.table_powerg_device.insert(data=content_values)
768
+
769
+ # Weather
770
+ case self.db.table_weather.uri:
771
+ self.db.table_weather.insert(data=content_values)
772
+ self._controller.state.sync_weather_data(self.get_weather_from_db())
773
+
732
774
  case _:
733
775
  LOGGER.debug("iq2meid inserting unknow uri:%s", uri)
734
776
  LOGGER.debug(data)
@@ -814,13 +856,35 @@ class QolsysPanel(QolsysObservable):
814
856
 
815
857
  return scenes
816
858
 
859
+ def get_weather_from_db(self) -> QolsysWeather:
860
+ weather = QolsysWeather()
861
+ forecast_dic_list: list[dict] = self.db.get_weather()
862
+
863
+ forecast_obj_list = []
864
+ for forecast in forecast_dic_list:
865
+ forecast_obj_list.append(QolsysForecast(forecast))
866
+
867
+ # Create weather array
868
+ weather.update(forecast_obj_list)
869
+
870
+ return weather
871
+
817
872
  def get_zones_from_db(self) -> list[QolsysZone]:
818
873
  zones = []
819
874
  zones_list: list[dict] = self.db.get_zones()
820
875
 
821
876
  # Create sensors array
822
877
  for zone_info in zones_list:
823
- zones.append(QolsysZone(zone_info,self._settings))
878
+ new_zone = QolsysZone(zone_info,self._controller.settings)
879
+
880
+ if new_zone.current_capability == "POWERG":
881
+ LOGGER.debug("Loading PowerG device info for zone %s", new_zone.zone_id)
882
+ powerg_dict = self.db.get_powerg(short_id= new_zone.shortID)
883
+ LOGGER.debug("PowerG device info: %s", powerg_dict)
884
+ if powerg_dict is not None:
885
+ new_zone.update_powerg(powerg_dict)
886
+
887
+ zones.append(new_zone)
824
888
 
825
889
  return zones
826
890
 
@@ -898,3 +962,7 @@ class QolsysPanel(QolsysObservable):
898
962
  LOGGER.debug("Users list:")
899
963
  for user in self._users:
900
964
  LOGGER.debug("User: %s", user["id"])
965
+
966
+ LOGGER.debug("*** Plugin Information ***")
967
+ LOGGER.debug("Motion Delay Enabled: %s", self._controller.settings.motion_sensor_delay)
968
+ LOGGER.debug("Motion Delay Value: %s", self._controller.settings.motion_sensor_delay_sec)
@@ -44,7 +44,7 @@ class QolsysPartition(QolsysObservable):
44
44
  self._command_arm_entry_delay = True
45
45
 
46
46
  @property
47
- def id(self) -> int:
47
+ def id(self) -> str:
48
48
  return self._id
49
49
 
50
50
  @property
@@ -1,34 +1,24 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
4
+ from abc import abstractmethod
5
+ from typing import TYPE_CHECKING
2
6
 
3
7
  from .observable import QolsysObservable
4
- from .panel import QolsysPanel
5
- from .settings import QolsysSettings
6
- from .state import QolsysState
7
8
 
8
9
  LOGGER = logging.getLogger(__name__)
9
10
 
11
+ if TYPE_CHECKING:
12
+ from .controller import QolsysController
10
13
 
11
- class QolsysPlugin:
12
- def __init__(self, state: QolsysState, panel: QolsysPanel, settings: QolsysSettings) -> None:
13
-
14
- self._state: QolsysState = state
15
- self._panel: QolsysPanel = panel
16
- self._settings: QolsysSettings = settings
17
14
 
15
+ class QolsysPlugin:
16
+ def __init__(self, controller: QolsysController) -> None:
17
+ self._controller = controller
18
18
  self.connected = False
19
19
  self.connected_observer = QolsysObservable()
20
20
 
21
+ @abstractmethod
21
22
  def config(self) -> None:
22
23
  pass
23
24
 
24
- @property
25
- def state(self) -> QolsysState:
26
- return self._state
27
-
28
- @property
29
- def panel(self) -> QolsysPanel:
30
- return self._panel
31
-
32
- @property
33
- def settings(self) -> QolsysSettings:
34
- return self._settings
@@ -9,7 +9,7 @@ class QolsysPluginC4(QolsysPlugin):
9
9
  def __init__(self) -> None:
10
10
 
11
11
  # C4 Integration
12
- self._token = ""
12
+ raise NotImplementedError("C4 Plugin Not Yet Implemented") # noqa: EM101
13
13
 
14
14
  def config(self, panel_ip: str, token: str) -> bool: # noqa: ARG002
15
15
  LOGGER.warning("C4Plugin: Configuring Plugin")