simo 2.0.42__py3-none-any.whl → 2.1.2__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 simo might be problematic. Click here for more details.
- simo/__pycache__/asgi.cpython-38.pyc +0 -0
- simo/__pycache__/settings.cpython-38.pyc +0 -0
- simo/__pycache__/wsgi.cpython-38.pyc +0 -0
- simo/asgi.py +1 -1
- simo/core/__init__.py +1 -0
- simo/core/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/core/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/__pycache__/api.cpython-38.pyc +0 -0
- simo/core/__pycache__/api_meta.cpython-38.pyc +0 -0
- simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
- simo/core/__pycache__/apps.cpython-38.pyc +0 -0
- simo/core/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/core/__pycache__/base_types.cpython-38.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/core/__pycache__/dynamic_settings.cpython-38.pyc +0 -0
- simo/core/__pycache__/form_fields.cpython-38.pyc +0 -0
- simo/core/__pycache__/forms.cpython-38.pyc +0 -0
- simo/core/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/core/__pycache__/managers.cpython-38.pyc +0 -0
- simo/core/__pycache__/models.cpython-38.pyc +0 -0
- simo/core/__pycache__/permissions.cpython-38.pyc +0 -0
- simo/core/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/core/__pycache__/signal_receivers.cpython-38.pyc +0 -0
- simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
- simo/core/__pycache__/views.cpython-38.pyc +0 -0
- simo/core/admin.py +26 -26
- simo/core/api.py +22 -2
- simo/core/api_meta.py +23 -13
- simo/core/app_widgets.py +6 -0
- simo/core/apps.py +13 -0
- simo/core/auto_urls.py +2 -3
- simo/core/base_types.py +1 -0
- simo/core/controllers.py +57 -0
- simo/core/dynamic_settings.py +0 -8
- simo/core/form_fields.py +93 -0
- simo/core/forms.py +16 -101
- simo/core/gateways.py +1 -1
- simo/core/managers.py +14 -1
- simo/core/migrations/0037_auto_20240606_1057.py +33 -0
- simo/core/migrations/0038_remove_instance_cover_image_and_more.py +30 -0
- simo/core/migrations/__pycache__/0037_auto_20240606_1057.cpython-38.pyc +0 -0
- simo/core/migrations/__pycache__/0038_remove_instance_cover_image_and_more.cpython-38.pyc +0 -0
- simo/core/models.py +30 -16
- simo/core/permissions.py +6 -3
- simo/core/serializers.py +77 -5
- simo/core/signal_receivers.py +25 -0
- simo/core/static/admin/css/simo.css +14 -0
- simo/core/tasks.py +82 -49
- simo/core/templates/admin/controller_widgets/button.html +8 -0
- simo/core/templates/admin/core/component_change_form.html +97 -0
- simo/core/templates/admin/formset_widget.html +88 -118
- simo/core/templates/admin/formset_widget_old.html +122 -0
- simo/core/templates/admin/user_tools.html +0 -3
- simo/core/templates/admin/wizard/wizard_add.html +16 -9
- simo/core/utils/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/utils/__pycache__/cache.cpython-38.pyc +0 -0
- simo/core/utils/__pycache__/formsets.cpython-38.pyc +0 -0
- simo/core/utils/admin.py +11 -0
- simo/core/utils/cache.py +15 -0
- simo/core/utils/formsets.py +11 -18
- simo/core/views.py +2 -85
- simo/fleet/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/models.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/utils.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/views.cpython-38.pyc +0 -0
- simo/fleet/auto_urls.py +7 -1
- simo/fleet/controllers.py +194 -31
- simo/fleet/forms.py +223 -87
- simo/fleet/gateways.py +53 -2
- simo/fleet/migrations/0036_auto_20240605_0702.py +68 -0
- simo/fleet/migrations/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.py +27 -0
- simo/fleet/migrations/__pycache__/0036_auto_20240605_0702.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.cpython-38.pyc +0 -0
- simo/fleet/models.py +35 -6
- simo/fleet/socket_consumers.py +1 -1
- simo/fleet/templates/fleet/controllers_info/button.md +16 -0
- simo/fleet/utils.py +31 -1
- simo/fleet/views.py +45 -0
- simo/generic/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/generic/__pycache__/forms.cpython-38.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/generic/controllers.py +61 -16
- simo/generic/forms.py +0 -3
- simo/generic/gateways.py +2 -0
- simo/generic/templates/admin/controller_widgets/blinds.html +2 -1
- simo/generic/templates/admin/controller_widgets/weather_forecast.html +1 -1
- simo/generic/templates/generic/controllers_info/dummy.md +3 -0
- simo/generic/templates/generic/controllers_info/stateselect.md +2 -0
- simo/management/__init__.py +0 -0
- simo/management/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/management/__pycache__/on_http_start.cpython-38.pyc +0 -0
- simo/{_hub_template → management/_hub_template}/hub/nginx.conf +2 -2
- simo/{auto_update.py → management/auto_update.py} +3 -0
- simo/{cli.py → management/copy_template.py} +3 -16
- simo/management/install.py +258 -0
- simo/{on_http_start.py → management/on_http_start.py} +22 -2
- simo/settings.py +20 -4
- simo/users/__init__.py +1 -0
- simo/users/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/users/__pycache__/admin.cpython-38.pyc +0 -0
- simo/users/__pycache__/apps.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/apps.py +9 -0
- simo/users/migrations/__pycache__/0029_alter_instanceuser_options_instanceuser_order.cpython-38.pyc +0 -0
- simo/users/migrations/__pycache__/0030_alter_instanceuser_options_remove_instanceuser_order.cpython-38.pyc +0 -0
- simo/users/models.py +16 -3
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/METADATA +5 -3
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/RECORD +122 -95
- simo-2.1.2.dist-info/entry_points.txt +2 -0
- simo/__pycache__/on_http_start.cpython-38.pyc +0 -0
- simo/wsgi.py +0 -7
- /simo/{_hub_template → management/_hub_template}/hub/asgi.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/celeryc.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/manage.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/settings.py +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/supervisor.conf +0 -0
- /simo/{_hub_template → management/_hub_template}/hub/urls.py +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/LICENSE.md +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/WHEEL +0 -0
- {simo-2.0.42.dist-info → simo-2.1.2.dist-info}/top_level.txt +0 -0
simo/fleet/controllers.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from django.utils.translation import gettext_lazy as _
|
|
3
|
+
from django.db.transaction import atomic
|
|
3
4
|
from simo.core.events import GatewayObjectCommand
|
|
4
5
|
from simo.core.controllers import (
|
|
5
6
|
BinarySensor as BaseBinarySensor,
|
|
7
|
+
Button as BaseButton,
|
|
6
8
|
NumericSensor as BaseNumericSensor,
|
|
7
9
|
Switch as BaseSwitch, Dimmer as BaseDimmer,
|
|
8
10
|
MultiSensor as BaseMultiSensor, RGBWLight as BaseRGBWLight
|
|
@@ -15,18 +17,20 @@ from simo.core.utils.serialization import (
|
|
|
15
17
|
serialize_form_data, deserialize_form_data
|
|
16
18
|
)
|
|
17
19
|
from simo.generic.controllers import Blinds as GenericBlinds
|
|
18
|
-
from .models import Colonel
|
|
20
|
+
from .models import Colonel, ColonelPin
|
|
19
21
|
from .gateways import FleetGatewayHandler
|
|
20
22
|
from .forms import (
|
|
21
23
|
ColonelPinChoiceField,
|
|
22
|
-
ColonelBinarySensorConfigForm,
|
|
24
|
+
ColonelBinarySensorConfigForm, ColonelButtonConfigForm,
|
|
23
25
|
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm,
|
|
24
26
|
ColonelNumericSensorConfigForm, ColonelRGBLightConfigForm,
|
|
25
27
|
ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
|
|
26
28
|
BME680SensorConfigForm, MPC9808SensorConfigForm,
|
|
27
29
|
DualMotorValveForm, BlindsConfigForm, BurglarSmokeDetectorConfigForm,
|
|
28
30
|
TTLockConfigForm, DALIDeviceConfigForm, DaliLampForm, DaliGearGroupForm,
|
|
29
|
-
|
|
31
|
+
DaliSwitchConfigForm,
|
|
32
|
+
DaliOccupancySensorConfigForm, DALILightSensorConfigForm,
|
|
33
|
+
DALIButtonConfigForm
|
|
30
34
|
)
|
|
31
35
|
|
|
32
36
|
|
|
@@ -67,19 +71,39 @@ class FleeDeviceMixin:
|
|
|
67
71
|
config[key] = val
|
|
68
72
|
return config
|
|
69
73
|
|
|
74
|
+
def _fix_pin_relations(self):
|
|
75
|
+
pass
|
|
76
|
+
|
|
70
77
|
|
|
71
78
|
class BasicSensorMixin:
|
|
72
79
|
gateway_class = FleetGatewayHandler
|
|
73
80
|
|
|
81
|
+
def _get_occupied_pins(self):
|
|
82
|
+
return [
|
|
83
|
+
self.component.config['pin_no'],
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
@atomic
|
|
87
|
+
def _fix_pin_relations(self):
|
|
88
|
+
colonel = Colonel.objects.filter(
|
|
89
|
+
id=self.component.config.get('colonel', 0)
|
|
90
|
+
).first()
|
|
91
|
+
if not colonel:
|
|
92
|
+
return
|
|
93
|
+
cp = ColonelPin.objects.filter(
|
|
94
|
+
colonel=colonel, no=self.component.config['pin_no']
|
|
95
|
+
).first()
|
|
96
|
+
if self.component.config.get('pin') != cp.id:
|
|
97
|
+
self.component.config['pin'] = cp.id
|
|
98
|
+
self.component.save()
|
|
74
99
|
|
|
75
100
|
|
|
76
101
|
class BinarySensor(FleeDeviceMixin, BasicSensorMixin, BaseBinarySensor):
|
|
77
102
|
config_form = ColonelBinarySensorConfigForm
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
]
|
|
104
|
+
|
|
105
|
+
class Button(FleeDeviceMixin, BasicSensorMixin, BaseButton):
|
|
106
|
+
config_form = ColonelButtonConfigForm
|
|
83
107
|
|
|
84
108
|
|
|
85
109
|
class BurglarSmokeDetector(BinarySensor):
|
|
@@ -92,6 +116,26 @@ class BurglarSmokeDetector(BinarySensor):
|
|
|
92
116
|
self.component.config['sensor_pin_no']
|
|
93
117
|
]
|
|
94
118
|
|
|
119
|
+
@atomic
|
|
120
|
+
def _fix_pin_relations(self):
|
|
121
|
+
colonel = Colonel.objects.filter(
|
|
122
|
+
id=self.component.config.get('colonel', 0)
|
|
123
|
+
).first()
|
|
124
|
+
if not colonel:
|
|
125
|
+
return
|
|
126
|
+
cp = ColonelPin.objects.filter(
|
|
127
|
+
colonel=colonel, no=self.component.config['power_pin_no']
|
|
128
|
+
).first()
|
|
129
|
+
if self.component.config.get('power_pin') != cp.id:
|
|
130
|
+
self.component.config['power_pin'] = cp.id
|
|
131
|
+
self.component.save()
|
|
132
|
+
cp = ColonelPin.objects.filter(
|
|
133
|
+
colonel=colonel, no=self.component.config['sensor_pin_no']
|
|
134
|
+
).first()
|
|
135
|
+
if self.component.config.get('sensor_pin') != cp.id:
|
|
136
|
+
self.component.config['sensor_pin'] = cp.id
|
|
137
|
+
self.component.save()
|
|
138
|
+
|
|
95
139
|
|
|
96
140
|
# class AnalogSensor(FleeDeviceMixin, BasicSensorMixin, BaseNumericSensor):
|
|
97
141
|
# config_form = ColonelNumericSensorConfigForm
|
|
@@ -107,11 +151,6 @@ class DS18B20Sensor(FleeDeviceMixin, BasicSensorMixin, BaseNumericSensor):
|
|
|
107
151
|
config_form = DS18B20SensorConfigForm
|
|
108
152
|
name = "DS18B20 Temperature sensor"
|
|
109
153
|
|
|
110
|
-
def _get_occupied_pins(self):
|
|
111
|
-
return [
|
|
112
|
-
self.component.config['pin_no'],
|
|
113
|
-
]
|
|
114
|
-
|
|
115
154
|
|
|
116
155
|
class BaseClimateSensor(FleeDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
117
156
|
app_widget = NumericSensorWidget
|
|
@@ -119,7 +158,7 @@ class BaseClimateSensor(FleeDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
|
119
158
|
def __init__(self, *args, **kwargs):
|
|
120
159
|
super().__init__(*args, **kwargs)
|
|
121
160
|
self.sys_temp_units = 'C'
|
|
122
|
-
if
|
|
161
|
+
if self.component.zone.instance.units_of_measure == 'imperial':
|
|
123
162
|
self.sys_temp_units = 'F'
|
|
124
163
|
|
|
125
164
|
@property
|
|
@@ -158,18 +197,15 @@ class DHTSensor(BaseClimateSensor):
|
|
|
158
197
|
config_form = ColonelDHTSensorConfigForm
|
|
159
198
|
name = "DHT climate sensor"
|
|
160
199
|
|
|
161
|
-
def _get_occupied_pins(self):
|
|
162
|
-
return [
|
|
163
|
-
self.component.config['pin_no'],
|
|
164
|
-
]
|
|
165
|
-
|
|
166
200
|
|
|
167
|
-
class BME680Sensor(
|
|
201
|
+
class BME680Sensor(FleeDeviceMixin, BaseMultiSensor):
|
|
202
|
+
gateway_class = FleetGatewayHandler
|
|
168
203
|
config_form = BME680SensorConfigForm
|
|
169
204
|
name = "BME680 Climate Sensor (I2C)"
|
|
170
205
|
|
|
171
206
|
|
|
172
|
-
class MPC9808TempSensor(FleeDeviceMixin,
|
|
207
|
+
class MPC9808TempSensor(FleeDeviceMixin, BaseNumericSensor):
|
|
208
|
+
gateway_class = FleetGatewayHandler
|
|
173
209
|
config_form = MPC9808SensorConfigForm
|
|
174
210
|
name = "MPC9808 Temperature Sensor (I2C)"
|
|
175
211
|
|
|
@@ -180,10 +216,47 @@ class BasicOutputMixin:
|
|
|
180
216
|
|
|
181
217
|
def _get_occupied_pins(self):
|
|
182
218
|
pins = [self.component.config['output_pin_no']]
|
|
183
|
-
for
|
|
184
|
-
|
|
219
|
+
for ctrl in self.component.config.get('controls', []):
|
|
220
|
+
if 'pin_no' in ctrl:
|
|
221
|
+
pins.append(ctrl['pin_no'])
|
|
185
222
|
return pins
|
|
186
223
|
|
|
224
|
+
@atomic
|
|
225
|
+
def _fix_pin_relations(self):
|
|
226
|
+
colonel = Colonel.objects.filter(
|
|
227
|
+
id=self.component.config.get('colonel', 0)
|
|
228
|
+
).first()
|
|
229
|
+
if not colonel:
|
|
230
|
+
return
|
|
231
|
+
cp = ColonelPin.objects.filter(
|
|
232
|
+
colonel=colonel, no=self.component.config['output_pin_no']
|
|
233
|
+
).first()
|
|
234
|
+
if self.component.config.get('output_pin') != cp.id:
|
|
235
|
+
self.component.config['output_pin'] = cp.id
|
|
236
|
+
|
|
237
|
+
for ctrl in self.component.config.get('controls', []):
|
|
238
|
+
if 'pin_no' not in ctrl:
|
|
239
|
+
continue
|
|
240
|
+
if not ctrl.get('input').startswith('pin-'):
|
|
241
|
+
continue
|
|
242
|
+
cp = ColonelPin.objects.filter(
|
|
243
|
+
colonel=colonel, no=ctrl['pin_no']
|
|
244
|
+
).first()
|
|
245
|
+
if not cp:
|
|
246
|
+
continue
|
|
247
|
+
ctrl['input'] = f'pin-{cp.id}'
|
|
248
|
+
|
|
249
|
+
self.component.save()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _ctrl(self, ctrl_no, ctrl_event, method):
|
|
253
|
+
GatewayObjectCommand(
|
|
254
|
+
self.component.gateway,
|
|
255
|
+
Colonel(id=self.component.config['colonel']),
|
|
256
|
+
id=self.component.id, command='call', method='ctrl',
|
|
257
|
+
args=[ctrl_no, ctrl_event, method]
|
|
258
|
+
).publish()
|
|
259
|
+
|
|
187
260
|
|
|
188
261
|
class Switch(FleeDeviceMixin, BasicOutputMixin, BaseSwitch):
|
|
189
262
|
config_form = ColonelSwitchConfigForm
|
|
@@ -211,8 +284,37 @@ class Switch(FleeDeviceMixin, BasicOutputMixin, BaseSwitch):
|
|
|
211
284
|
).publish()
|
|
212
285
|
|
|
213
286
|
|
|
287
|
+
class FadeMixin:
|
|
288
|
+
|
|
289
|
+
def __init__(self, *args, **kwargs):
|
|
290
|
+
super().__init__(*args, **kwargs)
|
|
291
|
+
self.component.last_fade_direction = 0
|
|
292
|
+
|
|
293
|
+
def fade_up(self):
|
|
294
|
+
self.component.last_fade_direction = 1
|
|
295
|
+
GatewayObjectCommand(
|
|
296
|
+
self.component.gateway,
|
|
297
|
+
Colonel(id=self.component.config['colonel']),
|
|
298
|
+
id=self.component.id, command='call', method='fade_up'
|
|
299
|
+
).publish()
|
|
300
|
+
|
|
301
|
+
def fade_down(self):
|
|
302
|
+
self.component.last_fade_direction = -1
|
|
303
|
+
GatewayObjectCommand(
|
|
304
|
+
self.component.gateway,
|
|
305
|
+
Colonel(id=self.component.config['colonel']),
|
|
306
|
+
id=self.component.id, command='call', method='fade_down'
|
|
307
|
+
).publish()
|
|
308
|
+
|
|
309
|
+
def fade_stop(self):
|
|
310
|
+
GatewayObjectCommand(
|
|
311
|
+
self.component.gateway,
|
|
312
|
+
Colonel(id=self.component.config['colonel']),
|
|
313
|
+
id=self.component.id, command='call', method='fade_stop'
|
|
314
|
+
).publish()
|
|
315
|
+
|
|
214
316
|
|
|
215
|
-
class PWMOutput(FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
317
|
+
class PWMOutput(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
216
318
|
name = "Dimmer"
|
|
217
319
|
config_form = ColonelPWMOutputConfigForm
|
|
218
320
|
|
|
@@ -262,6 +364,7 @@ class PWMOutput(FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
262
364
|
return value
|
|
263
365
|
|
|
264
366
|
|
|
367
|
+
|
|
265
368
|
class RGBLight(FleeDeviceMixin, BasicOutputMixin, BaseRGBWLight):
|
|
266
369
|
config_form = ColonelRGBLightConfigForm
|
|
267
370
|
|
|
@@ -278,6 +381,26 @@ class DualMotorValve(FleeDeviceMixin, BasicOutputMixin, BaseSwitch):
|
|
|
278
381
|
self.component.config['close_pin_no']
|
|
279
382
|
]
|
|
280
383
|
|
|
384
|
+
@atomic
|
|
385
|
+
def _fix_pin_relations(self):
|
|
386
|
+
colonel = Colonel.objects.filter(
|
|
387
|
+
id=self.component.config.get('colonel', 0)
|
|
388
|
+
).first()
|
|
389
|
+
if not colonel:
|
|
390
|
+
return
|
|
391
|
+
cp = ColonelPin.objects.filter(
|
|
392
|
+
colonel=colonel, no=self.component.config['open_pin_no']
|
|
393
|
+
).first()
|
|
394
|
+
if self.component.config.get('open_pin') != cp.id:
|
|
395
|
+
self.component.config['open_pin'] = cp.id
|
|
396
|
+
cp = ColonelPin.objects.filter(
|
|
397
|
+
colonel=colonel, no=self.component.config['close_pin_no']
|
|
398
|
+
).first()
|
|
399
|
+
if self.component.config.get('close_pin') != cp.id:
|
|
400
|
+
self.component.config['close_pin'] = cp.id
|
|
401
|
+
|
|
402
|
+
self.component.save()
|
|
403
|
+
|
|
281
404
|
|
|
282
405
|
class Blinds(FleeDeviceMixin, BasicOutputMixin, GenericBlinds):
|
|
283
406
|
gateway_class = FleetGatewayHandler
|
|
@@ -288,10 +411,41 @@ class Blinds(FleeDeviceMixin, BasicOutputMixin, GenericBlinds):
|
|
|
288
411
|
self.component.config['open_pin_no'],
|
|
289
412
|
self.component.config['close_pin_no']
|
|
290
413
|
]
|
|
291
|
-
for
|
|
292
|
-
|
|
414
|
+
for ctrl in self.component.config.get('controls', []):
|
|
415
|
+
if 'pin_no' in ctrl:
|
|
416
|
+
pins.append(ctrl['pin_no'])
|
|
293
417
|
return pins
|
|
294
418
|
|
|
419
|
+
@atomic
|
|
420
|
+
def _fix_pin_relations(self):
|
|
421
|
+
colonel = Colonel.objects.filter(
|
|
422
|
+
id=self.component.config.get('colonel', 0)
|
|
423
|
+
).first()
|
|
424
|
+
if not colonel:
|
|
425
|
+
return
|
|
426
|
+
cp = ColonelPin.objects.filter(
|
|
427
|
+
colonel=colonel, no=self.component.config['open_pin_no']
|
|
428
|
+
).first()
|
|
429
|
+
if self.component.config.get('open_pin') != cp.id:
|
|
430
|
+
self.component.config['open_pin'] = cp.id
|
|
431
|
+
cp = ColonelPin.objects.filter(
|
|
432
|
+
colonel=colonel, no=self.component.config['close_pin_no']
|
|
433
|
+
).first()
|
|
434
|
+
if self.component.config.get('close_pin') != cp.id:
|
|
435
|
+
self.component.config['close_pin'] = cp.id
|
|
436
|
+
for ctrl in self.component.config.get('controls', []):
|
|
437
|
+
if 'pin_no' not in ctrl:
|
|
438
|
+
continue
|
|
439
|
+
if not ctrl.get('input').startswith('pin-'):
|
|
440
|
+
continue
|
|
441
|
+
cp = ColonelPin.objects.filter(
|
|
442
|
+
colonel=colonel, no=ctrl['pin_no']
|
|
443
|
+
).first()
|
|
444
|
+
if not cp:
|
|
445
|
+
continue
|
|
446
|
+
ctrl['input'] = f'pin-{cp.id}'
|
|
447
|
+
self.component.save()
|
|
448
|
+
|
|
295
449
|
|
|
296
450
|
class TTLock(FleeDeviceMixin, Lock):
|
|
297
451
|
gateway_class = FleetGatewayHandler
|
|
@@ -315,6 +469,7 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
315
469
|
).publish()
|
|
316
470
|
|
|
317
471
|
@classmethod
|
|
472
|
+
@atomic
|
|
318
473
|
def _process_discovery(cls, started_with, data):
|
|
319
474
|
if data['discovery-result'] == 'fail':
|
|
320
475
|
if data['result'] == 0:
|
|
@@ -510,6 +665,7 @@ class DALIDevice(FleeDeviceMixin, ControllerBase):
|
|
|
510
665
|
).publish()
|
|
511
666
|
|
|
512
667
|
@classmethod
|
|
668
|
+
@atomic
|
|
513
669
|
def _process_discovery(cls, started_with, data):
|
|
514
670
|
if data['discovery-result'] == 'fail':
|
|
515
671
|
if data['result'] == 1:
|
|
@@ -545,6 +701,8 @@ class DALIDevice(FleeDeviceMixin, ControllerBase):
|
|
|
545
701
|
|
|
546
702
|
started_with = deserialize_form_data(started_with)
|
|
547
703
|
started_with['name'] += f" {data['result']['config']['da']}"
|
|
704
|
+
if data['result'].get('di') is not None:
|
|
705
|
+
started_with['name'] += f" - {data['result']['di']}"
|
|
548
706
|
started_with['controller_uid'] = controller_uid
|
|
549
707
|
started_with['base_type'] = controller_cls.base_type
|
|
550
708
|
form = controller_cls.config_form(
|
|
@@ -566,10 +724,6 @@ class DALIDevice(FleeDeviceMixin, ControllerBase):
|
|
|
566
724
|
'config': json.loads(json.dumps(new_component.config))
|
|
567
725
|
}
|
|
568
726
|
}
|
|
569
|
-
# Perform default config update on initial component setup
|
|
570
|
-
new_component.meta[
|
|
571
|
-
'finalization_data'
|
|
572
|
-
]['comp_config']['config']['boot_update'] = True
|
|
573
727
|
new_component.save()
|
|
574
728
|
GatewayObjectCommand(
|
|
575
729
|
new_component.gateway, Colonel(
|
|
@@ -595,14 +749,14 @@ class DALIDevice(FleeDeviceMixin, ControllerBase):
|
|
|
595
749
|
).publish()
|
|
596
750
|
|
|
597
751
|
|
|
598
|
-
class DALILamp(BaseDimmer, DALIDevice):
|
|
752
|
+
class DALILamp(FadeMixin, BaseDimmer, DALIDevice):
|
|
599
753
|
family = 'dali'
|
|
600
754
|
manual_add = False
|
|
601
755
|
name = 'DALI Lamp'
|
|
602
756
|
config_form = DaliLampForm
|
|
603
757
|
|
|
604
758
|
|
|
605
|
-
class DALIGearGroup(FleeDeviceMixin, BaseDimmer):
|
|
759
|
+
class DALIGearGroup(FadeMixin, FleeDeviceMixin, BaseDimmer):
|
|
606
760
|
gateway_class = FleetGatewayHandler
|
|
607
761
|
family = 'dali'
|
|
608
762
|
manual_add = True
|
|
@@ -632,9 +786,11 @@ class DALIGearGroup(FleeDeviceMixin, BaseDimmer):
|
|
|
632
786
|
|
|
633
787
|
|
|
634
788
|
class DALIRelay(BaseSwitch, DALIDevice):
|
|
789
|
+
'''Not tested with a real device yet'''
|
|
635
790
|
family = 'dali'
|
|
636
791
|
manual_add = False
|
|
637
792
|
name = 'DALI Relay'
|
|
793
|
+
config_form = DaliSwitchConfigForm
|
|
638
794
|
|
|
639
795
|
|
|
640
796
|
class DALIOccupancySensor(BaseBinarySensor, DALIDevice):
|
|
@@ -650,3 +806,10 @@ class DALILightSensor(BaseNumericSensor, DALIDevice):
|
|
|
650
806
|
name = 'DALI Light Sensor'
|
|
651
807
|
default_value_units = 'lux'
|
|
652
808
|
config_form = DALILightSensorConfigForm
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
class DALIButton(BaseButton, DALIDevice):
|
|
812
|
+
family = 'dali'
|
|
813
|
+
manual_add = False
|
|
814
|
+
name = 'DALI Button'
|
|
815
|
+
config_form = DALIButtonConfigForm
|