qolsys-controller 0.0.28__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,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,16 +348,18 @@ 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
354
360
 
355
361
  eventName = data.get("eventName")
356
- dbOperation = data.get("dbOperation")
362
+ dbOperation = data.get("dbOperation","")
357
363
  uri = data.get("uri")
358
364
 
359
365
  match eventName:
@@ -361,14 +367,21 @@ class QolsysPanel(QolsysObservable):
361
367
  case "stopScreenCapture":
362
368
  pass
363
369
 
370
+ case "primaryDisconnect":
371
+ LOGGER.info("Main Panel Disconnect")
372
+
364
373
  case "dbChanged":
365
374
 
366
375
  match dbOperation:
367
376
 
368
377
  case "update":
369
- content_values = data.get("contentValues")
370
- selection = data.get("selection")
371
- 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)
372
385
 
373
386
  match uri:
374
387
 
@@ -387,7 +400,7 @@ class QolsysPanel(QolsysObservable):
387
400
  # Update Partition setting - Send notification if setting has changed
388
401
  if name in self.settings_partition:
389
402
  partition_id = content_values.get("partition_id", "")
390
- partition = self._state.partition(partition_id)
403
+ partition = self._controller.state.partition(partition_id)
391
404
  if partition is not None:
392
405
  match name:
393
406
  case "SYSTEM_STATUS":
@@ -403,7 +416,7 @@ class QolsysPanel(QolsysObservable):
403
416
  case self.db.table_sensor.uri:
404
417
  self.db.table_sensor.update(selection, selection_argument, content_values)
405
418
  zoneid = content_values.get("zoneid", "")
406
- zone = self._state.zone(zoneid)
419
+ zone = self._controller.state.zone(zone_id=zoneid)
407
420
  if zone is not None:
408
421
  zone.update(content_values)
409
422
 
@@ -415,7 +428,7 @@ class QolsysPanel(QolsysObservable):
415
428
  self.db.table_state.update(selection, selection_argument, content_values)
416
429
 
417
430
  if name in self.state_partition:
418
- partition = self._state.partition(partition_id)
431
+ partition = self._controller.state.partition(partition_id)
419
432
  if partition is not None:
420
433
  match name:
421
434
  case "ALARM_STATE":
@@ -440,7 +453,7 @@ class QolsysPanel(QolsysObservable):
440
453
  case self.db.table_partition.uri:
441
454
  self.db.table_partition.update(selection, selection_argument, content_values)
442
455
  partition_id = content_values.get("partition_id", "")
443
- partition = self._state.partition(partition_id)
456
+ partition = self._controller.state.partition(partition_id)
444
457
  if partition is not None:
445
458
  partition.update_partition(content_values)
446
459
 
@@ -453,7 +466,7 @@ class QolsysPanel(QolsysObservable):
453
466
  case self.db.table_dimmer.uri:
454
467
  self.db.table_dimmer.update(selection, selection_argument, content_values)
455
468
  node_id = content_values.get("node_id", "")
456
- node = self._state.zwave_device(node_id)
469
+ node = self._controller.state.zwave_device(node_id)
457
470
  if node is not None and isinstance(node, QolsysDimmer):
458
471
  node.update_dimmer(content_values)
459
472
 
@@ -461,7 +474,7 @@ class QolsysPanel(QolsysObservable):
461
474
  case self.db.table_thermostat.uri:
462
475
  self.db.table_thermostat.update(selection, selection_argument, content_values)
463
476
  node_id = content_values.get("node_id", "")
464
- node = self._state.zwave_device(node_id)
477
+ node = self._controller.state.zwave_device(node_id)
465
478
  if node is not None and isinstance(node, QolsysThermostat):
466
479
  node.update_thermostat(content_values)
467
480
 
@@ -469,7 +482,7 @@ class QolsysPanel(QolsysObservable):
469
482
  case self.db.table_doorlock.uri:
470
483
  self.db.table_doorlock.update(selection, selection_argument, content_values)
471
484
  node_id = content_values.get("node_id", "")
472
- node = self._state.zwave_device(node_id)
485
+ node = self._controller.state.zwave_device(node_id)
473
486
  if node is not None and isinstance(node, QolsysLock):
474
487
  node.update_lock(content_values)
475
488
 
@@ -477,7 +490,7 @@ class QolsysPanel(QolsysObservable):
477
490
  case self.db.table_zwave_node.uri:
478
491
  self.db.table_zwave_node.update(selection, selection_argument, content_values)
479
492
  node_id = content_values.get("node_id", "")
480
- node = self._state.zwave_device(node_id)
493
+ node = self._controller.state.zwave_device(node_id)
481
494
  if node is not None:
482
495
  node.update_base(content_values)
483
496
 
@@ -504,24 +517,51 @@ class QolsysPanel(QolsysObservable):
504
517
  case self.db.table_scene.uri:
505
518
  self.db.table_scene.update(selection, selection_argument, content_values)
506
519
  scene_id = content_values.get("scene_id", "")
507
- scene = self._state.scene(scene_id)
520
+ scene = self._controller.state.scene(scene_id)
508
521
  if scene is not None and isinstance(node, QolsysScene):
509
522
  scene.update(content_values)
510
523
 
524
+ # Update Trouble Conditions
525
+ case self.db.table_trouble_conditions.uri:
526
+ self.db.table_trouble_conditions.update(selection,selection_argument,content_values)
527
+ # No action needed
528
+
529
+ # Update EU_EVENT:
530
+ case self.db.table_eu_event.uri:
531
+ self.db.table_eu_event.update(selection,selection_argument,content_values)
532
+ # No action needed
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)
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())
511
547
 
512
548
  case _:
513
549
  LOGGER.debug("iq2meid updating unknow uri:%s", uri)
514
550
  LOGGER.debug(data)
515
551
 
516
552
  case "delete":
517
- selection = data.get("selection")
518
- 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)
519
559
 
520
560
  match uri:
521
561
 
522
562
  case self.db.table_sensor.uri:
523
563
  self.db.table_sensor.delete(selection, selection_argument)
524
- self._state.sync_zones_data(self.get_zones_from_db())
564
+ self._controller.state.sync_zones_data(self.get_zones_from_db())
525
565
  # Notify delete zone
526
566
 
527
567
  case self.db.table_iqremotesettings.uri:
@@ -542,7 +582,7 @@ class QolsysPanel(QolsysObservable):
542
582
 
543
583
  case self.db.table_alarmedsensor.uri:
544
584
  self.db.table_alarmedsensor.delete(selection, selection_argument)
545
- self._state.sync_partitions_data(self.get_partitions_from_db())
585
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
546
586
 
547
587
  case self.db.table_history.uri:
548
588
  self.db.table_history.delete(selection, selection_argument)
@@ -554,19 +594,19 @@ class QolsysPanel(QolsysObservable):
554
594
 
555
595
  case self.db.table_doorlock.uri:
556
596
  self.db.table_doorlock.delete(selection, selection_argument)
557
- 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())
558
598
 
559
599
  case self.db.table_dimmer.uri:
560
600
  self.db.table_dimmer.delete(selection, selection_argument)
561
- 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())
562
602
 
563
603
  case self.db.table_thermostat.uri:
564
604
  self.db.table_thermostat.delete(selection, selection_argument)
565
- 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())
566
606
 
567
607
  case self.db.table_zwave_node.uri:
568
608
  self.db.table_zwave_node.delete(selection, selection_argument)
569
- 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())
570
610
 
571
611
  case self.db.table_automation.uri:
572
612
  self.db.table_automation.delete(selection, selection_argument)
@@ -574,7 +614,7 @@ class QolsysPanel(QolsysObservable):
574
614
 
575
615
  case self.db.table_partition.uri:
576
616
  self.db.table_partition.delete(selection, selection_argument)
577
- self._state.sync_partitions_data(self.get_partitions_from_db())
617
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
578
618
 
579
619
  case self.db.table_user.uri:
580
620
  self.db.table_user.delete(selection, selection_argument)
@@ -584,6 +624,16 @@ class QolsysPanel(QolsysObservable):
584
624
  self.db.table_dashboard_msgs.delete(selection, selection_argument)
585
625
  # No action needed
586
626
 
627
+ case self.db.table_eu_event.uri:
628
+ self.db.table_eu_event.delete(selection,selection_argument)
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
+
587
637
  case _:
588
638
  LOGGER.debug("iq2meid deleting unknown uri:%s", uri)
589
639
  LOGGER.debug(data)
@@ -601,16 +651,16 @@ class QolsysPanel(QolsysObservable):
601
651
  new_value = content_values.get("value", "")
602
652
  if name in self.state_partition:
603
653
  partition_id = content_values.get("partition_id", "")
604
- partition = self._state.partition(partition_id)
654
+ partition = self._controller.state.partition(partition_id)
605
655
  if partition is not None:
606
656
  match name:
607
657
  case "ALARM_STATE":
608
658
  partition.alarm_state = PartitionAlarmState(new_value)
609
659
 
610
660
  # Inser Partition Content Provider
611
- case self.db.table_partition:
661
+ case self.db.table_partition.uri:
612
662
  self.db.table_partition.insert(data=content_values)
613
- self._state.sync_partitions_data(self.get_partitions_from_db())
663
+ self._controller.state.sync_partitions_data(self.get_partitions_from_db())
614
664
 
615
665
  # Insert Settings Content Provider
616
666
  case self.db.table_qolsyssettings.uri:
@@ -621,7 +671,7 @@ class QolsysPanel(QolsysObservable):
621
671
  new_value = content_values.get("value", "")
622
672
  if name in self.settings_partition:
623
673
  partition_id = content_values.get("partition_id", "")
624
- partition = self._state.partition(partition_id)
674
+ partition = self._controller.state.partition(partition_id)
625
675
  if partition is not None:
626
676
  match name:
627
677
  case "SYSTEM_STATUS":
@@ -651,27 +701,27 @@ class QolsysPanel(QolsysObservable):
651
701
  # Sensor Content Provider
652
702
  case self.db.table_sensor.uri:
653
703
  self.db.table_sensor.insert(data=content_values)
654
- self._state.sync_zones_data(self.get_zones_from_db())
704
+ self._controller.state.sync_zones_data(self.get_zones_from_db())
655
705
 
656
706
  # Door Lock Content Provider
657
707
  case self.db.table_doorlock.uri:
658
708
  self.db.table_doorlock.insert(data=content_values)
659
- 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())
660
710
 
661
711
  # Dimmer Content Provider
662
712
  case self.db.table_dimmer.uri:
663
713
  self.db.table_dimmer.insert(data=content_values)
664
- 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())
665
715
 
666
716
  # Thermostat Content Provider
667
717
  case self.db.table_thermostat.uri:
668
718
  self.db.table_thermostat.insert(data=content_values)
669
- 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())
670
720
 
671
721
  # ZWave Node Content Provider
672
722
  case self.db.table_zwave_node.uri:
673
723
  self.db.table_zwave_node.insert(data=content_values)
674
- 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())
675
725
 
676
726
  # HistoryContentProvider
677
727
  case self.db.table_history.uri:
@@ -684,7 +734,7 @@ class QolsysPanel(QolsysObservable):
684
734
  partition_id = content_values.get("partition_id", "")
685
735
  self.db.table_alarmedsensor.insert(data=content_values)
686
736
 
687
- partition = self._state.partition(partition_id)
737
+ partition = self._controller.state.partition(partition_id)
688
738
  if partition is not None:
689
739
  partition.append_alarm_type([PartitionAlarmType(content_values.get("sgroup", ""))])
690
740
 
@@ -708,6 +758,19 @@ class QolsysPanel(QolsysObservable):
708
758
  self.db.table_dashboard_msgs.insert(data=content_values)
709
759
  # No action needed
710
760
 
761
+ # EU_EVENT
762
+ case self.db.table_eu_event.uri:
763
+ self.db.table_eu_event.insert(data=content_values)
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
+
711
774
  case _:
712
775
  LOGGER.debug("iq2meid inserting unknow uri:%s", uri)
713
776
  LOGGER.debug(data)
@@ -793,13 +856,35 @@ class QolsysPanel(QolsysObservable):
793
856
 
794
857
  return scenes
795
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
+
796
872
  def get_zones_from_db(self) -> list[QolsysZone]:
797
873
  zones = []
798
874
  zones_list: list[dict] = self.db.get_zones()
799
875
 
800
876
  # Create sensors array
801
877
  for zone_info in zones_list:
802
- zones.append(QolsysZone(zone_info))
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)
803
888
 
804
889
  return zones
805
890
 
@@ -877,3 +962,7 @@ class QolsysPanel(QolsysObservable):
877
962
  LOGGER.debug("Users list:")
878
963
  for user in self._users:
879
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)
@@ -41,9 +41,10 @@ class QolsysPartition(QolsysObservable):
41
41
  self._command_exit_sounds = True
42
42
  self._command_arm_stay_instant = True
43
43
  self._command_arm_stay_silent_disarming = False
44
+ self._command_arm_entry_delay = True
44
45
 
45
46
  @property
46
- def id(self) -> int:
47
+ def id(self) -> str:
47
48
  return self._id
48
49
 
49
50
  @property
@@ -86,6 +87,10 @@ class QolsysPartition(QolsysObservable):
86
87
  def command_arm_stay_silent_disarming(self) -> bool:
87
88
  return self._command_arm_stay_silent_disarming
88
89
 
90
+ @property
91
+ def command_arm_entry_delay(self) -> bool:
92
+ return self._command_arm_entry_delay
93
+
89
94
  @system_status.setter
90
95
  def system_status(self, new_value: PartitionSystemStatus) -> None:
91
96
  if self._system_status != new_value:
@@ -190,6 +195,14 @@ class QolsysPartition(QolsysObservable):
190
195
  LOGGER.debug("Partition%s (%s) - arm_stay_silent_disarming: %s", self._id, self._name, value)
191
196
  self.notify()
192
197
 
198
+ @command_arm_entry_delay.setter
199
+ def command_arm_entry_delay(self, value:bool) -> None:
200
+ self._command_arm_entry_delay = value
201
+ LOGGER.debug("Partition%s (%s) - command_arm_entry_delay: %s", self._id, self._name, value)
202
+ self.notify()
203
+
204
+
205
+
193
206
  def update_partition(self, data: dict) -> None:
194
207
  # Check if we are updating same partition_id
195
208
  partition_id_update = data.get("partition_id", "")
@@ -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")