qolsys-controller 0.0.44__py3-none-any.whl → 0.0.87__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 (81) hide show
  1. qolsys_controller/adc_device.py +202 -0
  2. qolsys_controller/adc_service.py +139 -0
  3. qolsys_controller/adc_service_garagedoor.py +35 -0
  4. qolsys_controller/controller.py +1040 -20
  5. qolsys_controller/database/db.py +108 -29
  6. qolsys_controller/database/table.py +90 -60
  7. qolsys_controller/database/table_alarmedsensor.py +2 -2
  8. qolsys_controller/database/table_automation.py +0 -1
  9. qolsys_controller/database/table_country_locale.py +0 -1
  10. qolsys_controller/database/table_dashboard_msgs.py +1 -2
  11. qolsys_controller/database/table_dimmerlight.py +0 -1
  12. qolsys_controller/database/table_doorlock.py +0 -1
  13. qolsys_controller/database/table_eu_event.py +1 -2
  14. qolsys_controller/database/table_heat_map.py +0 -2
  15. qolsys_controller/database/table_history.py +4 -1
  16. qolsys_controller/database/table_iqremotesettings.py +0 -2
  17. qolsys_controller/database/table_iqrouter_network_config.py +0 -1
  18. qolsys_controller/database/table_iqrouter_user_device.py +0 -2
  19. qolsys_controller/database/table_master_slave.py +0 -1
  20. qolsys_controller/database/table_nest_device.py +0 -1
  21. qolsys_controller/database/table_output_rules.py +0 -1
  22. qolsys_controller/database/table_partition.py +0 -1
  23. qolsys_controller/database/table_pgm_outputs.py +0 -2
  24. qolsys_controller/database/table_powerg_device.py +0 -2
  25. qolsys_controller/database/table_qolsyssettings.py +0 -2
  26. qolsys_controller/database/table_scene.py +0 -2
  27. qolsys_controller/database/table_sensor.py +2 -2
  28. qolsys_controller/database/table_sensor_group.py +23 -0
  29. qolsys_controller/database/table_shades.py +0 -2
  30. qolsys_controller/database/table_smartsocket.py +12 -3
  31. qolsys_controller/database/table_state.py +0 -1
  32. qolsys_controller/database/table_tcc.py +0 -1
  33. qolsys_controller/database/table_thermostat.py +3 -1
  34. qolsys_controller/database/table_trouble_conditions.py +0 -2
  35. qolsys_controller/database/table_user.py +0 -2
  36. qolsys_controller/database/table_virtual_device.py +13 -3
  37. qolsys_controller/database/table_weather.py +0 -2
  38. qolsys_controller/database/table_zigbee_device.py +0 -1
  39. qolsys_controller/database/table_zwave_association_group.py +0 -1
  40. qolsys_controller/database/table_zwave_history.py +0 -1
  41. qolsys_controller/database/table_zwave_node.py +3 -1
  42. qolsys_controller/database/table_zwave_other.py +0 -1
  43. qolsys_controller/enum.py +42 -13
  44. qolsys_controller/enum_adc.py +28 -0
  45. qolsys_controller/enum_zwave.py +210 -36
  46. qolsys_controller/errors.py +14 -12
  47. qolsys_controller/mdns.py +7 -4
  48. qolsys_controller/mqtt_command.py +125 -0
  49. qolsys_controller/mqtt_command_queue.py +5 -4
  50. qolsys_controller/observable.py +2 -2
  51. qolsys_controller/panel.py +304 -156
  52. qolsys_controller/partition.py +149 -127
  53. qolsys_controller/pki.py +69 -97
  54. qolsys_controller/scene.py +30 -28
  55. qolsys_controller/settings.py +96 -50
  56. qolsys_controller/state.py +221 -34
  57. qolsys_controller/task_manager.py +11 -14
  58. qolsys_controller/users.py +25 -0
  59. qolsys_controller/utils_mqtt.py +8 -16
  60. qolsys_controller/weather.py +71 -0
  61. qolsys_controller/zone.py +243 -214
  62. qolsys_controller/zwave_device.py +234 -93
  63. qolsys_controller/zwave_dimmer.py +55 -49
  64. qolsys_controller/zwave_energy_clamp.py +15 -0
  65. qolsys_controller/zwave_garagedoor.py +3 -1
  66. qolsys_controller/zwave_generic.py +5 -3
  67. qolsys_controller/zwave_lock.py +51 -44
  68. qolsys_controller/zwave_outlet.py +3 -1
  69. qolsys_controller/zwave_service_meter.py +192 -0
  70. qolsys_controller/zwave_service_multilevelsensor.py +119 -0
  71. qolsys_controller/zwave_thermometer.py +21 -0
  72. qolsys_controller/zwave_thermostat.py +249 -143
  73. qolsys_controller-0.0.87.dist-info/METADATA +89 -0
  74. qolsys_controller-0.0.87.dist-info/RECORD +77 -0
  75. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/WHEEL +1 -1
  76. qolsys_controller/plugin.py +0 -34
  77. qolsys_controller/plugin_c4.py +0 -17
  78. qolsys_controller/plugin_remote.py +0 -1298
  79. qolsys_controller-0.0.44.dist-info/METADATA +0 -93
  80. qolsys_controller-0.0.44.dist-info/RECORD +0 -68
  81. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/licenses/LICENSE +0 -0
@@ -1,37 +1,211 @@
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 MeterType(IntEnum):
5
+ UNKNOWN = 0x00
6
+ ELECTRIC_METER = 0x01
7
+ GAZ_METER = 0x02
8
+ WATER_METER = 0x03
9
+ HEATING = 0x04
10
+ COOLING = 0x05
11
+ RESERVED = 0x6
12
+
13
+
14
+ class MeterRateType(IntEnum):
15
+ UNSPECIFIED = 0x00
16
+ IMPORT = 0x01
17
+ EXPORT = 0x02
18
+ RESERVED = 0x03
19
+
20
+
21
+ class ZWaveMultilevelSensorScale(Enum):
22
+ TEMPERATURE_CELSIUS = "temperature_celsius"
23
+ TEMPERATURE_FAHRENHEIT = "temperature_fahrenheit"
24
+ RELATIVE_HUMIDITY = "relative_humidity"
25
+ WIND_DIRECTION = "wind_direction"
26
+ BAROMETRIC_PRESSURE = "barometric_pressure"
27
+ DEW_POINT = "dew_point"
28
+ RAIN_RATE = "rain_rate"
29
+ TIDE_LEVEL = "tide_level"
30
+ WEIGHT = "weight"
31
+ VOLTS = "volts"
32
+ AMPS = "amps"
33
+ WATTS = "watts"
34
+ DISTANCE = "distance"
35
+ ANGLE_POSITION = "angle_position"
36
+ ROTATION = "rotation"
37
+ WATER_TEMPERATURE_CELSIUS = "water_temperature_celsius"
38
+ WATER_TEMPERATURE_FAHRENHEIT = "water_temperature_fahrenheit"
39
+ LUMINOSITY_LUX = "luminosity_lux"
40
+ UNKNOWN = "unknown"
41
+
42
+
43
+ class ZWaveUnknownMeterScale(IntEnum):
44
+ UNKNOWN = 0
45
+
46
+
47
+ class ZWaveElectricMeterScale(IntEnum):
48
+ KWH = 0
49
+ KVAH = 1
50
+ WATTS = 2
51
+ PULSE_COUNT = 3
52
+ VOLTS = 4
53
+ AMPS = 5
54
+ POWER_FACTOR = 6
55
+ KVAR = 7
56
+ KVARH = 8
57
+
58
+
59
+ class ZWaveGasMeterScale(IntEnum):
60
+ CUBIC_METERS = 0
61
+ CUBIC_FEET = 1
62
+ PULSE_COUNT = 3
63
+
64
+
65
+ class ZWaveWaterMeterScale(IntEnum):
66
+ CUBIC_METERS = 0
67
+ CUBIC_FEET = 1
68
+ US_GALLONS = 2
69
+ PULSE_COUNT = 3
70
+
71
+
72
+ class ZWaveThermalMeterScale(IntEnum):
73
+ KWH = 0
74
+ PULSE_COUNT = 3
75
+
76
+
77
+ class ThermostatMode(IntEnum):
78
+ OFF = 0x00
79
+ HEAT = 0x01
80
+ COOL = 0x02
81
+ AUTO = 0x03
82
+ AUX_HEAT = 0x04
83
+ RESUME = 0x05
84
+ FAN_ONLY = 0x06
85
+ FURNACE = 0x07
86
+ DRY_AIR = 0x08
87
+ MOIST_AIR = 0x09
88
+ AUTO_CHANGEOVER = 0x0A
89
+ ENERGY_SAVE_HEAT = 0x0B
90
+ ENERGY_SAVE_COOL = 0x0C
91
+ AWAY = 0x0F
92
+
93
+
94
+ BITMASK_SUPPORTED_THERMOSTAT_MODE = {
95
+ 0: ThermostatMode.OFF,
96
+ 1: ThermostatMode.HEAT,
97
+ 2: ThermostatMode.COOL,
98
+ 3: ThermostatMode.AUTO,
99
+ 4: ThermostatMode.AUX_HEAT,
100
+ 5: ThermostatMode.RESUME,
101
+ 6: ThermostatMode.FAN_ONLY,
102
+ 7: ThermostatMode.FURNACE,
103
+ }
104
+
105
+
106
+ class ThermostatSetpointMode(IntEnum):
107
+ HEATING = 0x01
108
+ COOLING = 0x02
109
+ FURNACE = 0x03
110
+ DRY_AIR = 0x04
111
+ MOIST_AIR = 0x05
112
+ AUTO_CHANGEOVER = 0x06
113
+ ECO_HEATING = 0x07
114
+ ECO_COOLING = 0x08
115
+ AWAY_HEATING = 0x09
116
+ AWAY_COOLING = 0x10
117
+
118
+
119
+ BITMASK_SUPPORTED_THERMOSTAT_SETPOINT_MODE = {
120
+ 0: ThermostatSetpointMode.HEATING,
121
+ 1: ThermostatSetpointMode.COOLING,
122
+ 2: ThermostatSetpointMode.FURNACE,
123
+ 3: ThermostatSetpointMode.DRY_AIR,
124
+ 4: ThermostatSetpointMode.MOIST_AIR,
125
+ 5: ThermostatSetpointMode.AUTO_CHANGEOVER,
126
+ 6: ThermostatSetpointMode.ECO_HEATING,
127
+ 7: ThermostatSetpointMode.ECO_COOLING,
128
+ 8: ThermostatSetpointMode.AWAY_HEATING,
129
+ 9: ThermostatSetpointMode.AWAY_COOLING,
130
+ }
131
+
132
+
133
+ class ThermostatFanMode(IntEnum):
134
+ AUTO_LOW = 0x00
135
+ LOW = 0x01
136
+ AUTO_HIGH = 0x02
137
+ HIGH = 0x03
138
+ AUTO_MEDIUM = 0x04
139
+ MEDIUM = 0x05
140
+ CIRCULATION = 0x06
141
+ HUMIDITY_CIRCULATION = 0x07
142
+ LEFT_RIGHT = 0x08
143
+ UP_DOWN = 0x09
144
+ QUIET = 0x0A
145
+ EXTERNAL_CIRCULATION = 0x0800
146
+
147
+
148
+ BITMASK_SUPPORTED_THERMOSTAT_FAN_MODE = {
149
+ 0: ThermostatFanMode.AUTO_LOW,
150
+ 1: ThermostatFanMode.LOW,
151
+ 2: ThermostatFanMode.AUTO_HIGH,
152
+ 3: ThermostatFanMode.HIGH,
153
+ 4: ThermostatFanMode.AUTO_MEDIUM,
154
+ 5: ThermostatFanMode.MEDIUM,
155
+ 6: ThermostatFanMode.CIRCULATION,
156
+ 7: ThermostatFanMode.HUMIDITY_CIRCULATION,
157
+ }
158
+
159
+
160
+ class ZwaveCommandClass(IntEnum):
161
+ SwitchBinary = 0x25
162
+ SwitchMultilevel = 0x26
163
+ SensorMultiLevel = 0x31
164
+ Meter = 0x32
165
+ ThermostatMode = 0x40
166
+ ThermostatSetPoint = 0x43
167
+ ThermostatFanMode = 0x44
168
+ ThermostatFanState = 0x45
169
+ DoorLock = 0x62
170
+ Alarm = 0x71
171
+
172
+
173
+ class ZwaveCommand(IntEnum):
174
+ SET = 0x01
175
+ GET = 0x02
176
+
177
+
178
+ class ZwaveDeviceClass(Enum):
179
+ Unknown = 0x00
180
+ GenericController = 0x01
181
+ StaticController = 0x02
182
+ AVControlPoint = 0x03
183
+ Display = 0x04
184
+ DoorLock = 0x05
185
+ Thermostat = 0x06
186
+ SensorBinary = 0x07
187
+ SensorMultilevel = 0x08
188
+ Meter = 0x09
189
+ EntryControl = 0x0A
190
+ SemiInteroperable = 0x0B
191
+ Button = 0x0C
192
+ RepeaterSlave = 0x0F
193
+ SwitchBinary = 0x10
194
+ SwitchMultilevel = 0x11
195
+ RemoteSwitchBinary = 0x12
196
+ RemoteSwitchMultilevel = 0x13
197
+ SwitchToggleBinary = 0x14
198
+ SwitchToggleMultilevel = 0x15
199
+ ZIPNode = 0x16
200
+ Ventilation = 0x17
201
+ WindowCovering = 0x18
202
+ BarrierOperator = 0x20
203
+ SensorNotification = 0x21
204
+ SoundSwitch = 0x22
205
+ MeterPulse = 0x23
206
+ ColorSwitch = 0x24
207
+ ClimateControlSchedule = 0x25
208
+ RemoteAssociationActivator = 0x26
209
+ SceneController = 0x27
210
+ SceneSceneActuatorConfiguration = 0x28
211
+ SimpleAVControlPoint = 0x30
@@ -1,37 +1,39 @@
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
- class QolsysSslError(QolsysError):
12
+ class QolsysUserCodeError(QolsysError):
13
+ def __init__(self) -> None:
14
+ super().__init__("QolsysUserCodeError")
15
+
13
16
 
17
+ class QolsysSslError(QolsysError):
14
18
  def __init__(self) -> None:
15
19
  super().__init__("QolsysSslError")
16
20
 
17
21
 
18
22
  class QolsysMqttError(QolsysError):
19
-
20
23
  def __init__(self) -> None:
21
24
  super().__init__("QolsysMqttError")
22
25
 
23
26
 
24
27
  class QolsysSqlError(QolsysError):
25
-
26
- def __init__(self, operation: dict) -> None:
28
+ def __init__(self, operation: dict[str, Any]) -> None:
27
29
  super().__init__("QolsysSqlError")
28
30
 
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', "")}"
31
+ table = f"QolsysSqlError - table:{operation.get('table', '')}"
32
+ query = f"QolsysSqlError - query:{operation.get('query', '')}"
33
+ columns = f"QolsysSqlError - columns:{operation.get('columns', '')}"
34
+ content_values = f"QolsysSqlError - content_values:{operation.get('content_value', '')}"
35
+ selection = f"QolsysSqlError - selection:{operation.get('selection', '')}"
36
+ selection_argument = f"QolsysSqlError - selection_argument:{operation.get('selection_argument', '')}"
35
37
 
36
38
  e = f"""\n{table}\n{query}\n{columns}\n{content_values}\n{selection}\n{selection_argument}"""
37
39
  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,125 @@
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
+ # Node ID
95
+ "dataType": "int",
96
+ "dataValue": int(node_id),
97
+ },
98
+ {
99
+ # End Point
100
+ "dataType": "int",
101
+ "dataValue": 0,
102
+ },
103
+ {
104
+ # Z-Wave Payload
105
+ "dataType": "byteArray",
106
+ "dataValue": zwave_command,
107
+ },
108
+ {
109
+ # Transmit option ?
110
+ "dataType": "int",
111
+ "dataValue": 0,
112
+ },
113
+ {
114
+ # Priority
115
+ "dataType": "int",
116
+ "dataValue": 106,
117
+ },
118
+ {
119
+ # Callback ?
120
+ "dataType": "byteArray",
121
+ "dataValue": [0],
122
+ },
123
+ ]
124
+
125
+ 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]
@@ -17,12 +17,12 @@ class QolsysObservable:
17
17
  def unregister(self, observer: Callable[[], None]) -> None:
18
18
  self._observers.remove(observer)
19
19
 
20
- def notify(self, **payload) -> None: # noqa: ANN003
20
+ def notify(self) -> None:
21
21
  if self._batch_update_active:
22
22
  self._batch_update_change_detected = True
23
23
  else:
24
24
  for observer in self._observers:
25
- observer(self, **payload)
25
+ observer()
26
26
 
27
27
  def start_batch_update(self) -> None:
28
28
  self._batch_update_change_detected = False