simo 2.0.0__py3-none-any.whl → 2.0.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/core/controllers.py +22 -4
- simo/fleet/admin.py +10 -5
- simo/fleet/controllers.py +2 -0
- simo/fleet/migrations/0027_auto_20240306_0802.py +21 -21
- simo/fleet/models.py +29 -22
- simo/fleet/serializers.py +5 -0
- simo/generic/forms.py +6 -0
- simo/generic/models.py +15 -9
- simo/notifications/utils.py +1 -1
- simo/users/serializers.py +2 -2
- {simo-2.0.0.dist-info → simo-2.0.2.dist-info}/METADATA +1 -1
- {simo-2.0.0.dist-info → simo-2.0.2.dist-info}/RECORD +15 -15
- {simo-2.0.0.dist-info → simo-2.0.2.dist-info}/LICENSE.md +0 -0
- {simo-2.0.0.dist-info → simo-2.0.2.dist-info}/WHEEL +0 -0
- {simo-2.0.0.dist-info → simo-2.0.2.dist-info}/top_level.txt +0 -0
simo/core/controllers.py
CHANGED
|
@@ -275,6 +275,10 @@ class ControllerBase(ABC):
|
|
|
275
275
|
'val': icon if any(values) else None}
|
|
276
276
|
]
|
|
277
277
|
|
|
278
|
+
def poke(self):
|
|
279
|
+
'''Use this when component is dead to try and wake it up'''
|
|
280
|
+
pass
|
|
281
|
+
|
|
278
282
|
def _prepare_for_send(self, value):
|
|
279
283
|
return value
|
|
280
284
|
|
|
@@ -435,7 +439,19 @@ class BinarySensor(ControllerBase):
|
|
|
435
439
|
return value
|
|
436
440
|
|
|
437
441
|
|
|
438
|
-
class
|
|
442
|
+
class OnOffPokerMixin:
|
|
443
|
+
_poke_toggle = False
|
|
444
|
+
|
|
445
|
+
def poke(self):
|
|
446
|
+
if self._poke_toggle:
|
|
447
|
+
self._poke_toggle = False
|
|
448
|
+
self.turn_on()
|
|
449
|
+
else:
|
|
450
|
+
self._poke_toggle = True
|
|
451
|
+
self.turn_off()
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
class Dimmer(ControllerBase, TimerMixin, OnOffPokerMixin):
|
|
439
455
|
name = _("Dimmer")
|
|
440
456
|
base_type = 'dimmer'
|
|
441
457
|
app_widget = KnobWidget
|
|
@@ -444,6 +460,7 @@ class Dimmer(ControllerBase, TimerMixin):
|
|
|
444
460
|
default_config = {'min': 0.0, 'max': 100.0, 'inverse': False}
|
|
445
461
|
default_value = 0
|
|
446
462
|
|
|
463
|
+
|
|
447
464
|
def _prepare_for_send(self, value):
|
|
448
465
|
if isinstance(value, bool):
|
|
449
466
|
if value:
|
|
@@ -484,7 +501,8 @@ class Dimmer(ControllerBase, TimerMixin):
|
|
|
484
501
|
self.turn_on()
|
|
485
502
|
|
|
486
503
|
|
|
487
|
-
|
|
504
|
+
|
|
505
|
+
class DimmerPlus(ControllerBase, TimerMixin, OnOffPokerMixin):
|
|
488
506
|
name = _("Dimmer Plus")
|
|
489
507
|
base_type = 'dimmer-plus'
|
|
490
508
|
app_widget = KnobPlusWidget
|
|
@@ -564,7 +582,7 @@ class DimmerPlus(ControllerBase, TimerMixin):
|
|
|
564
582
|
self.turn_on()
|
|
565
583
|
|
|
566
584
|
|
|
567
|
-
class RGBWLight(ControllerBase, TimerMixin):
|
|
585
|
+
class RGBWLight(ControllerBase, TimerMixin, OnOffPokerMixin):
|
|
568
586
|
name = _("RGB(W) Light")
|
|
569
587
|
base_type = 'rgbw-light'
|
|
570
588
|
app_widget = RGBWidget
|
|
@@ -648,7 +666,7 @@ class MultiSwitchBase(ControllerBase):
|
|
|
648
666
|
return value
|
|
649
667
|
|
|
650
668
|
|
|
651
|
-
class Switch(MultiSwitchBase, TimerMixin):
|
|
669
|
+
class Switch(MultiSwitchBase, TimerMixin, OnOffPokerMixin):
|
|
652
670
|
name = _("Switch")
|
|
653
671
|
base_type = 'switch'
|
|
654
672
|
app_widget = SingleSwitchWidget
|
simo/fleet/admin.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from threading import Timer
|
|
1
2
|
from django.contrib import admin
|
|
2
3
|
from django.utils.safestring import mark_safe
|
|
3
4
|
from django.template.loader import render_to_string
|
|
@@ -78,14 +79,18 @@ class ColonelAdmin(admin.ModelAdmin):
|
|
|
78
79
|
return qs
|
|
79
80
|
return qs.filter(instance__in=request.user.instances)
|
|
80
81
|
|
|
82
|
+
def save_model(self, request, obj, form, change):
|
|
83
|
+
super().save_model(request, obj, form, change)
|
|
84
|
+
# give it one second to finish up with atomic transaction and
|
|
85
|
+
# send update_config command.
|
|
86
|
+
def update_colonel_config(colonel):
|
|
87
|
+
colonel.update_config()
|
|
88
|
+
Timer(1, update_colonel_config, [obj]).start()
|
|
89
|
+
|
|
90
|
+
|
|
81
91
|
def has_add_permission(self, request):
|
|
82
92
|
return False
|
|
83
93
|
|
|
84
|
-
def save_model(self, request, obj, form, change):
|
|
85
|
-
res = super().save_model(request, obj, form, change)
|
|
86
|
-
obj.update_config()
|
|
87
|
-
return res
|
|
88
|
-
|
|
89
94
|
def update_firmware(self, request, queryset):
|
|
90
95
|
count = 0
|
|
91
96
|
for colonel in queryset:
|
simo/fleet/controllers.py
CHANGED
|
@@ -308,6 +308,8 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
308
308
|
@classmethod
|
|
309
309
|
def _process_discovery(cls, started_with, data):
|
|
310
310
|
if data['discover-ttlock'] == 'fail':
|
|
311
|
+
if data['result'] == 0:
|
|
312
|
+
return {'error': 'Internal Colonel error. See Colonel logs.'}
|
|
311
313
|
if data['result'] == 1:
|
|
312
314
|
return {'error': 'TTLock not found.'}
|
|
313
315
|
elif data['result'] == 2:
|
|
@@ -7,7 +7,7 @@ from django.db import migrations
|
|
|
7
7
|
|
|
8
8
|
def forwards_func(apps, schema_editor):
|
|
9
9
|
from simo.fleet.utils import GPIO_PINS
|
|
10
|
-
from django.contrib.contenttypes.models import ContentType
|
|
10
|
+
#from django.contrib.contenttypes.models import ContentType
|
|
11
11
|
|
|
12
12
|
Colonel = apps.get_model('fleet', "Colonel")
|
|
13
13
|
ColonelPin = apps.get_model("fleet", "ColonelPin")
|
|
@@ -26,18 +26,18 @@ def forwards_func(apps, schema_editor):
|
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
for i2c in colonel.i2c_interfaces.all():
|
|
29
|
-
ct = ContentType.objects.get_for_model(i2c)
|
|
29
|
+
#ct = ContentType.objects.get_for_model(i2c)
|
|
30
30
|
|
|
31
31
|
scl_pin = new_pins[colonel.id][i2c.scl_pin_no]
|
|
32
|
-
scl_pin.occupied_by_content_type = ct
|
|
33
|
-
scl_pin.occupied_by_id = i2c.id
|
|
32
|
+
#scl_pin.occupied_by_content_type = ct
|
|
33
|
+
#scl_pin.occupied_by_id = i2c.id
|
|
34
34
|
scl_pin.save()
|
|
35
35
|
i2c.scl_pin = scl_pin
|
|
36
36
|
i2c.scl_pin.save()
|
|
37
37
|
|
|
38
38
|
sda_pin = new_pins[colonel.id][i2c.sda_pin_no]
|
|
39
|
-
sda_pin.occupied_by_content_type = ct
|
|
40
|
-
sda_pin.occupied_by_id = i2c.id
|
|
39
|
+
#sda_pin.occupied_by_content_type = ct
|
|
40
|
+
#sda_pin.occupied_by_id = i2c.id
|
|
41
41
|
sda_pin.save()
|
|
42
42
|
|
|
43
43
|
i2c.sda_pin = sda_pin
|
|
@@ -48,7 +48,7 @@ def forwards_func(apps, schema_editor):
|
|
|
48
48
|
for comp in Component.objects.filter(
|
|
49
49
|
controller_uid__startswith='simo.fleet.'
|
|
50
50
|
):
|
|
51
|
-
ct = ContentType.objects.get_for_model(comp)
|
|
51
|
+
#ct = ContentType.objects.get_for_model(comp)
|
|
52
52
|
try:
|
|
53
53
|
colonel = Colonel.objects.get(id=comp.config['colonel'])
|
|
54
54
|
except Exception as e:
|
|
@@ -64,8 +64,8 @@ def forwards_func(apps, schema_editor):
|
|
|
64
64
|
|
|
65
65
|
pin = new_pins[colonel.id][comp.config['pin_no']]
|
|
66
66
|
comp.config['pin'] = pin.pk
|
|
67
|
-
pin.occupied_by_content_type = ct
|
|
68
|
-
pin.occupied_by_id = comp.id
|
|
67
|
+
#pin.occupied_by_content_type = ct
|
|
68
|
+
#pin.occupied_by_id = comp.id
|
|
69
69
|
pin.save()
|
|
70
70
|
if 'power_pin' in comp.config:
|
|
71
71
|
comp.config['power_pin_no'] = comp.config.pop('power_pin')
|
|
@@ -77,8 +77,8 @@ def forwards_func(apps, schema_editor):
|
|
|
77
77
|
|
|
78
78
|
pin = new_pins[colonel.id][comp.config['power_pin_no']]
|
|
79
79
|
comp.config['power_pin'] = pin.pk
|
|
80
|
-
pin.occupied_by_content_type = ct
|
|
81
|
-
pin.occupied_by_id = comp.id
|
|
80
|
+
#pin.occupied_by_content_type = ct
|
|
81
|
+
#pin.occupied_by_id = comp.id
|
|
82
82
|
pin.save()
|
|
83
83
|
if 'sensor_pin' in comp.config:
|
|
84
84
|
comp.config['sensor_pin_no'] = comp.config.pop('sensor_pin')
|
|
@@ -90,8 +90,8 @@ def forwards_func(apps, schema_editor):
|
|
|
90
90
|
|
|
91
91
|
pin = new_pins[colonel.id][comp.config['sensor_pin_no']]
|
|
92
92
|
comp.config['sensor_pin'] = pin.pk
|
|
93
|
-
pin.occupied_by_content_type = ct
|
|
94
|
-
pin.occupied_by_id = comp.id
|
|
93
|
+
#pin.occupied_by_content_type = ct
|
|
94
|
+
#pin.occupied_by_id = comp.id
|
|
95
95
|
pin.save()
|
|
96
96
|
if 'output_pin' in comp.config:
|
|
97
97
|
comp.config['output_pin_no'] = comp.config.pop('output_pin')
|
|
@@ -103,8 +103,8 @@ def forwards_func(apps, schema_editor):
|
|
|
103
103
|
|
|
104
104
|
pin = new_pins[colonel.id][comp.config['output_pin_no']]
|
|
105
105
|
comp.config['output_pin'] = pin.pk
|
|
106
|
-
pin.occupied_by_content_type = ct
|
|
107
|
-
pin.occupied_by_id = comp.id
|
|
106
|
+
#pin.occupied_by_content_type = ct
|
|
107
|
+
#pin.occupied_by_id = comp.id
|
|
108
108
|
pin.save()
|
|
109
109
|
if 'open_pin' in comp.config:
|
|
110
110
|
comp.config['open_pin_no'] = comp.config.pop('open_pin')
|
|
@@ -116,8 +116,8 @@ def forwards_func(apps, schema_editor):
|
|
|
116
116
|
|
|
117
117
|
pin = new_pins[colonel.id][comp.config['open_pin_no']]
|
|
118
118
|
comp.config['open_pin'] = pin.pk
|
|
119
|
-
pin.occupied_by_content_type = ct
|
|
120
|
-
pin.occupied_by_id = comp.id
|
|
119
|
+
#pin.occupied_by_content_type = ct
|
|
120
|
+
#pin.occupied_by_id = comp.id
|
|
121
121
|
pin.save()
|
|
122
122
|
if 'close_pin' in comp.config:
|
|
123
123
|
comp.config['close_pin_no'] = comp.config.pop('close_pin')
|
|
@@ -129,8 +129,8 @@ def forwards_func(apps, schema_editor):
|
|
|
129
129
|
|
|
130
130
|
pin = new_pins[colonel.id][comp.config['close_pin_no']]
|
|
131
131
|
comp.config['close_pin'] = pin.pk
|
|
132
|
-
pin.occupied_by_content_type = ct
|
|
133
|
-
pin.occupied_by_id = comp.id
|
|
132
|
+
#pin.occupied_by_content_type = ct
|
|
133
|
+
#pin.occupied_by_id = comp.id
|
|
134
134
|
pin.save()
|
|
135
135
|
|
|
136
136
|
if 'controls' in comp.config:
|
|
@@ -146,8 +146,8 @@ def forwards_func(apps, schema_editor):
|
|
|
146
146
|
pin = new_pins[colonel.id][updated_controls['pin_no']]
|
|
147
147
|
updated_controls['pin'] = pin.pk
|
|
148
148
|
|
|
149
|
-
pin.occupied_by_content_type = ct
|
|
150
|
-
pin.occupied_by_id = comp.id
|
|
149
|
+
#pin.occupied_by_content_type = ct
|
|
150
|
+
#pin.occupied_by_id = comp.id
|
|
151
151
|
pin.save()
|
|
152
152
|
|
|
153
153
|
comp.config['controls'][i] = updated_controls
|
simo/fleet/models.py
CHANGED
|
@@ -82,8 +82,10 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
82
82
|
occupied_pins = models.JSONField(default=dict, blank=True)
|
|
83
83
|
|
|
84
84
|
logs_stream = models.BooleanField(
|
|
85
|
-
default=False, help_text="
|
|
86
|
-
"
|
|
85
|
+
default=False, help_text="ATENTION! Causes serious overhead!!! "
|
|
86
|
+
"Leave this off. "
|
|
87
|
+
"It causes Colonel websocket to run out of memory "
|
|
88
|
+
"and reset if a lot of data is being transmitted."
|
|
87
89
|
)
|
|
88
90
|
pwm_frequency = models.IntegerField(default=1, choices=(
|
|
89
91
|
(0, "3kHz"), (1, "22kHz")
|
|
@@ -161,10 +163,8 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
161
163
|
@transaction.atomic
|
|
162
164
|
def rebuild_occupied_pins(self):
|
|
163
165
|
for pin in ColonelPin.objects.filter(colonel=self):
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
pin.occupied_by_id = None
|
|
167
|
-
pin.save()
|
|
166
|
+
pin.occupied_by = None
|
|
167
|
+
pin.save()
|
|
168
168
|
|
|
169
169
|
for component in self.components.all():
|
|
170
170
|
try:
|
|
@@ -176,9 +176,16 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
176
176
|
pin.occupied_by = component
|
|
177
177
|
pin.save()
|
|
178
178
|
|
|
179
|
+
for interface in self.i2c_interfaces.all():
|
|
180
|
+
interface.sda_pin.occupied_by = interface
|
|
181
|
+
interface.sda_pin.save()
|
|
182
|
+
interface.scl_pin.occupied_by = interface
|
|
183
|
+
interface.scl_pin.save()
|
|
184
|
+
|
|
179
185
|
|
|
180
186
|
@transaction.atomic()
|
|
181
187
|
def move_to(self, other_colonel):
|
|
188
|
+
# TODO: Need to replace pins on components!
|
|
182
189
|
other_colonel.refresh_from_db()
|
|
183
190
|
assert list(other_colonel.components.all()) == [], \
|
|
184
191
|
"Other colonel must be completely empty!"
|
|
@@ -196,6 +203,7 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
196
203
|
|
|
197
204
|
for i2c_interface in self.i2c_interfaces.all():
|
|
198
205
|
I2CInterface.objects.create(
|
|
206
|
+
no=i2c_interface.no,
|
|
199
207
|
colonel=other_colonel, name=i2c_interface.name,
|
|
200
208
|
freq=i2c_interface.freq,
|
|
201
209
|
scl_pin=ColonelPin.objects.get(
|
|
@@ -261,22 +269,21 @@ class ColonelPin(models.Model):
|
|
|
261
269
|
|
|
262
270
|
|
|
263
271
|
@receiver(post_save, sender=Colonel)
|
|
264
|
-
def
|
|
265
|
-
if
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
)
|
|
272
|
+
def after_colonel_save(sender, instance, created, *args, **kwargs):
|
|
273
|
+
if created:
|
|
274
|
+
for no, data in GPIO_PINS.get(instance.type).items():
|
|
275
|
+
ColonelPin.objects.get_or_create(
|
|
276
|
+
colonel=instance, no=no,
|
|
277
|
+
input=data.get('input'), output=data.get('output'),
|
|
278
|
+
capacitive=data.get('capacitive'), adc=data.get('adc'),
|
|
279
|
+
native=data.get('native'), note=data.get('note')
|
|
280
|
+
)
|
|
281
|
+
if instance.type in ('ample-wall', 'game-changer'):
|
|
282
|
+
I2CInterface.objects.create(
|
|
283
|
+
colonel=instance, name='Main', no=0,
|
|
284
|
+
scl_pin=ColonelPin.objects.get(colonel=instance, no=4),
|
|
285
|
+
sda_pin=ColonelPin.objects.get(colonel=instance, no=15),
|
|
286
|
+
)
|
|
280
287
|
|
|
281
288
|
|
|
282
289
|
@receiver(pre_delete, sender=Component)
|
simo/fleet/serializers.py
CHANGED
|
@@ -45,3 +45,8 @@ class ColonelSerializer(serializers.ModelSerializer):
|
|
|
45
45
|
for pin in obj.pins.all():
|
|
46
46
|
result.append(ColonelPinSerializer(pin).data)
|
|
47
47
|
return result
|
|
48
|
+
|
|
49
|
+
def update(self, instance, validated_data):
|
|
50
|
+
instance = super().update(instance, validated_data)
|
|
51
|
+
instance.update_config()
|
|
52
|
+
return instance
|
simo/generic/forms.py
CHANGED
|
@@ -167,6 +167,12 @@ class AlarmGroupConfigForm(BaseComponentForm):
|
|
|
167
167
|
required=False,
|
|
168
168
|
help_text="Defines if this is your main/top global alarm group."
|
|
169
169
|
)
|
|
170
|
+
notify_on_breach = forms.IntegerField(
|
|
171
|
+
required=False, min_value=0,
|
|
172
|
+
help_text="Notify active users if "
|
|
173
|
+
"not disarmed within given number of seconds "
|
|
174
|
+
"after the breached."
|
|
175
|
+
)
|
|
170
176
|
has_alarm = False
|
|
171
177
|
|
|
172
178
|
|
simo/generic/models.py
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
from django.db import models
|
|
2
1
|
from threading import Timer
|
|
3
|
-
from django.utils.translation import gettext_lazy as _
|
|
4
2
|
from django.db.models.signals import pre_save, post_save, post_delete
|
|
5
3
|
from django.dispatch import receiver
|
|
6
4
|
from simo.core.models import Instance, Component
|
|
@@ -20,7 +18,8 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
20
18
|
|
|
21
19
|
for alarm_group in Component.objects.filter(
|
|
22
20
|
controller_uid=AlarmGroup.uid,
|
|
23
|
-
config__components__contains=instance.id
|
|
21
|
+
config__components__contains=instance.id,
|
|
22
|
+
config__notify_on_breach__gt=-1
|
|
24
23
|
).exclude(value='disarmed'):
|
|
25
24
|
stats = {
|
|
26
25
|
'disarmed': 0, 'pending-arm': 0, 'armed': 0, 'breached': 0
|
|
@@ -33,7 +32,6 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
33
32
|
alarm_group.config['stats'] = stats
|
|
34
33
|
alarm_group.save(update_fields=['config'])
|
|
35
34
|
|
|
36
|
-
alarm_group_value = alarm_group.value
|
|
37
35
|
if stats['disarmed'] == len(alarm_group.config['components']):
|
|
38
36
|
alarm_group_value = 'disarmed'
|
|
39
37
|
elif stats['armed'] == len(alarm_group.config['components']):
|
|
@@ -41,9 +39,11 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
41
39
|
elif stats['breached']:
|
|
42
40
|
if alarm_group.value != 'breached':
|
|
43
41
|
def notify_users_security_breach(alarm_group_component_id):
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
alarm_group_component = Component.objects.filter(
|
|
43
|
+
id=alarm_group_component_id, value='breached'
|
|
44
|
+
).first()
|
|
45
|
+
if not alarm_group_component:
|
|
46
|
+
return
|
|
47
47
|
breached_components = Component.objects.filter(
|
|
48
48
|
pk__in=alarm_group_component.config['components'],
|
|
49
49
|
arm_status='breached'
|
|
@@ -51,16 +51,22 @@ def handle_alarm_groups(sender, instance, *args, **kwargs):
|
|
|
51
51
|
body = "Security Breach! " + '; '.join(
|
|
52
52
|
[str(c) for c in breached_components]
|
|
53
53
|
)
|
|
54
|
+
from simo.notifications.utils import notify_users
|
|
54
55
|
notify_users(
|
|
56
|
+
alarm_group_component.zone.instance,
|
|
55
57
|
'alarm', str(alarm_group_component), body,
|
|
56
58
|
component=alarm_group_component
|
|
57
59
|
)
|
|
58
|
-
t = Timer(
|
|
60
|
+
t = Timer(
|
|
61
|
+
# give it one second to finish with other db processes.
|
|
62
|
+
alarm_group.config['notify_on_breach'] + 1,
|
|
63
|
+
notify_users_security_breach, [alarm_group.id]
|
|
64
|
+
)
|
|
59
65
|
t.start()
|
|
60
66
|
alarm_group_value = 'breached'
|
|
61
67
|
else:
|
|
62
68
|
alarm_group_value = 'pending-arm'
|
|
63
|
-
alarm_group.set(alarm_group_value)
|
|
69
|
+
alarm_group.controller.set(alarm_group_value)
|
|
64
70
|
|
|
65
71
|
|
|
66
72
|
@receiver(post_save, sender=Component)
|
simo/notifications/utils.py
CHANGED
|
@@ -14,7 +14,7 @@ def notify_users(instance, severity, title, body=None, component=None, users=Non
|
|
|
14
14
|
)
|
|
15
15
|
if not users:
|
|
16
16
|
users = User.objects.filter(
|
|
17
|
-
|
|
17
|
+
instance_roles__instance=instance,
|
|
18
18
|
instance_roles__is_active=True
|
|
19
19
|
)
|
|
20
20
|
for user in users:
|
simo/users/serializers.py
CHANGED
|
@@ -81,8 +81,8 @@ class FingerprintSerializer(serializers.ModelSerializer):
|
|
|
81
81
|
|
|
82
82
|
class Meta:
|
|
83
83
|
model = Fingerprint
|
|
84
|
-
fields = 'type', 'value', 'user'
|
|
85
|
-
read_only_fields = ('type', 'value')
|
|
84
|
+
fields = 'id', 'type', 'value', 'user'
|
|
85
|
+
read_only_fields = ('id', 'type', 'value')
|
|
86
86
|
|
|
87
87
|
def get_type(self, obj):
|
|
88
88
|
return obj.type
|
|
@@ -34,7 +34,7 @@ simo/core/auto_urls.py,sha256=0gu-IL7PHobrmKW6ksffiOkAYu-aIorykWdxRNtwGYo,1194
|
|
|
34
34
|
simo/core/autocomplete_views.py,sha256=JT5LA2_Wtr60XYSAIqaXFKFYPjrmkEf6yunXD9y2zco,4022
|
|
35
35
|
simo/core/base_types.py,sha256=yqbIZqBksrAkEuHRbt6iExwPDDy0K5II2NzRCkmOvMU,589
|
|
36
36
|
simo/core/context.py,sha256=98PXAMie43faRVBFkOG22uNpvGRNprcGhzjBFkrxaRY,1367
|
|
37
|
-
simo/core/controllers.py,sha256=
|
|
37
|
+
simo/core/controllers.py,sha256=bxJRpmREw8CsgDAiuVvpOl8HxHhZqrRM1qXTF_8afV4,26617
|
|
38
38
|
simo/core/dynamic_settings.py,sha256=U2WNL96JzVXdZh0EqMPWrxqO6BaRR2Eo5KTDqz7MC4o,1943
|
|
39
39
|
simo/core/events.py,sha256=LvtonJGNyCb6HLozs4EG0WZItnDwNdtnGQ4vTcnKvUs,4438
|
|
40
40
|
simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
|
|
@@ -10120,17 +10120,17 @@ simo/core/utils/validators.py,sha256=FRO6_K5HAO1OaC-LosApZjh-W3EA-IJZ53HnwEJgqiI
|
|
|
10120
10120
|
simo/core/utils/__pycache__/api.cpython-38.pyc,sha256=CuJq9GKQC8gbeCxmH2wQHZUmkIihVILSEIAoVYCFwH0,1575
|
|
10121
10121
|
simo/core/utils/__pycache__/serialization.cpython-38.pyc,sha256=zOo2M97bAC0Ed-iiNoVtcHvgdAYR8RwrF2bUwuf8Pus,1145
|
|
10122
10122
|
simo/fleet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10123
|
-
simo/fleet/admin.py,sha256=
|
|
10123
|
+
simo/fleet/admin.py,sha256=Vxp3yTNRVoDif_hwwBW3weeMNakQ3iZo-GC0VvdScfQ,5699
|
|
10124
10124
|
simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
|
|
10125
10125
|
simo/fleet/auto_urls.py,sha256=gAXTWUvsWkQHRdZGM_W_5iJBEsM4lY063kIx3f5LUqs,578
|
|
10126
10126
|
simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
|
|
10127
|
-
simo/fleet/controllers.py,sha256=
|
|
10127
|
+
simo/fleet/controllers.py,sha256=N8Qzdp2RPFrpZ_l9O4u8VjHWoY_WTWGg76s3V3oJqEs,13999
|
|
10128
10128
|
simo/fleet/forms.py,sha256=UGj1mK2Zbl2LRlvLtEDObeGfC2wcuHleRbePo1_Vx6I,34972
|
|
10129
10129
|
simo/fleet/gateways.py,sha256=xFsmF_SXYXK_kMJOCHkiInPJ_0VcPWz-kJDoMup2lT8,1576
|
|
10130
10130
|
simo/fleet/managers.py,sha256=kpfvvfdH4LDxddIBDpdAb5gsVk8Gb0-L9biFcj9OFPs,807
|
|
10131
|
-
simo/fleet/models.py,sha256=
|
|
10131
|
+
simo/fleet/models.py,sha256=6IzGv4jvLaRInzKX8cetHcD08f59HCLWRClYDQJJyKc,12588
|
|
10132
10132
|
simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
|
|
10133
|
-
simo/fleet/serializers.py,sha256=
|
|
10133
|
+
simo/fleet/serializers.py,sha256=zEpXAXxjk4Rf1JhlNnLTrs20qJggqjvIySbeHVo4Tt4,1505
|
|
10134
10134
|
simo/fleet/socket_consumers.py,sha256=HbkrV0i1TwBC38otu_2lzN6IlBdyZHVdXIVhU4y-YCM,18872
|
|
10135
10135
|
simo/fleet/utils.py,sha256=D0EGFbDmW8zyhyxf5ozGtRpo4Sy5Ov6ZixukBK_e2Do,3462
|
|
10136
10136
|
simo/fleet/views.py,sha256=PbdZpsM_7-oyKzuDX1A5WULNABA1_B7ISF70UJX97FE,1662
|
|
@@ -10175,7 +10175,7 @@ simo/fleet/migrations/0023_colonel_is_authorized.py,sha256=IoyPUR45axv9V6QsntPTj
|
|
|
10175
10175
|
simo/fleet/migrations/0024_colonel_pwm_frequency.py,sha256=nfTDs3GeIEkkiuQMB3_tc8TuyZSNOdQ2KhnJKTtQ9XE,498
|
|
10176
10176
|
simo/fleet/migrations/0025_auto_20240130_1334.py,sha256=dHcQnlF7LBp6ikx_s5AB_I19sQ-iMB8XJ1X1yoWVvBs,825
|
|
10177
10177
|
simo/fleet/migrations/0026_rename_i2cinterface_scl_pin_and_more.py,sha256=SEQxhgFsxWaUmfXaMOHHj0q8EqF9bt9PTOVuVa6wrQs,2752
|
|
10178
|
-
simo/fleet/migrations/0027_auto_20240306_0802.py,sha256=
|
|
10178
|
+
simo/fleet/migrations/0027_auto_20240306_0802.py,sha256=kOtLlCbbkqZu1zwzNZyA5rE_0TifF7tURdLCu_hzTLE,5972
|
|
10179
10179
|
simo/fleet/migrations/0028_remove_i2cinterface_scl_pin_no_and_more.py,sha256=CeoFQPIu3jb4Gtyu5FhRjhl_mKhowMoEdtFU1oWD4UE,450
|
|
10180
10180
|
simo/fleet/migrations/0029_alter_i2cinterface_scl_pin_and_more.py,sha256=aquymc1ZcUVgdrqZxl3viN6kiCHtw4HjgL6n4d0cSpQ,886
|
|
10181
10181
|
simo/fleet/migrations/0030_colonelpin_label_alter_colonel_type.py,sha256=5T5bmQxPZrG0UseCLd7ssV-AeFF3O4T_DFxLu3whSqg,706
|
|
@@ -10217,9 +10217,9 @@ simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
10217
10217
|
simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
|
|
10218
10218
|
simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
|
|
10219
10219
|
simo/generic/controllers.py,sha256=Fs95mRBJgT5ZNMnxxwQJ_94TJ7Y_O0IygWSgfjLZzU0,51912
|
|
10220
|
-
simo/generic/forms.py,sha256=
|
|
10220
|
+
simo/generic/forms.py,sha256=HYctQMudlMpQRxkI67C6NShaM1dAzo0J-qbu-AFpozU,20194
|
|
10221
10221
|
simo/generic/gateways.py,sha256=aHU0mA0ADNVzw3EXb8paXI5DI-gNd4CrGtaV5qDhILY,15499
|
|
10222
|
-
simo/generic/models.py,sha256
|
|
10222
|
+
simo/generic/models.py,sha256=d00Q-UXtt7mG9MdPpZ3mXnxKjwlTI2FgCEklZpGBk7s,3629
|
|
10223
10223
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10224
10224
|
simo/generic/socket_consumers.py,sha256=NfTQGYtVAc864IoogZRxf_0xpDPM0eMCWn0SlKA5P7Y,1751
|
|
10225
10225
|
simo/generic/static/weather_icons/01d@2x.png,sha256=TZfWi6Rfddb2P-oldWWcjUiuCHiU9Yrc5hyrQAhF26I,948
|
|
@@ -10266,7 +10266,7 @@ simo/notifications/admin.py,sha256=y_gmHYXbDh98LUUa-lp9DilTIgM6-pIujWPQPLQsJo8,8
|
|
|
10266
10266
|
simo/notifications/api.py,sha256=GXQpq68ULBaJpU8w3SJKaCKuxYGWYehKnGeocGB1RVc,1783
|
|
10267
10267
|
simo/notifications/models.py,sha256=VZcvweii59j89nPKlWeUSJ44Qz3ZLjJ6mXN6uB9F1Sw,2506
|
|
10268
10268
|
simo/notifications/serializers.py,sha256=altDEAPWwOhxRcEzE9-34jL8EFpyf3vPoEdAPoVLfGc,523
|
|
10269
|
-
simo/notifications/utils.py,sha256=
|
|
10269
|
+
simo/notifications/utils.py,sha256=5CtKOvX0vbWLXFvJD_8WfWulMEp1FuMwrfCGDLHySdA,907
|
|
10270
10270
|
simo/notifications/migrations/0001_initial.py,sha256=Zh69AQ-EKlQKfqfnMDVRcxvo1MxRY-TFLCdnNcgqi6g,2003
|
|
10271
10271
|
simo/notifications/migrations/0002_notification_instance.py,sha256=B3msbMeKvsuq-V7gvRADRjj5PFLayhi3pQvHZjqzO5g,563
|
|
10272
10272
|
simo/notifications/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -10279,7 +10279,7 @@ simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCa
|
|
|
10279
10279
|
simo/users/middleware.py,sha256=9epN8xDcnYAMoEjAeJGg4W9e54szTgh48LKz3rlywFI,1287
|
|
10280
10280
|
simo/users/models.py,sha256=f59mkQBpq_fFLDUa-44b1qWleB-TvGdC1M0G67huJMg,18498
|
|
10281
10281
|
simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
|
|
10282
|
-
simo/users/serializers.py,sha256=
|
|
10282
|
+
simo/users/serializers.py,sha256=yrWghK7ONxfzkjO3LbDLK1WPxsPBMYUegdm29qovjjo,2486
|
|
10283
10283
|
simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
|
|
10284
10284
|
simo/users/sso_views.py,sha256=-XI67TvQ7SN3goU4OuAHyn84u_1vtusvpn7Pu0K97zo,4648
|
|
10285
10285
|
simo/users/tasks.py,sha256=v9J7t4diB0VnqUDVZAQ8H-rlr4ZR14bgEUuEGpODyOI,854
|
|
@@ -10343,8 +10343,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10343
10343
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10344
10344
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10345
10345
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10346
|
-
simo-2.0.
|
|
10347
|
-
simo-2.0.
|
|
10348
|
-
simo-2.0.
|
|
10349
|
-
simo-2.0.
|
|
10350
|
-
simo-2.0.
|
|
10346
|
+
simo-2.0.2.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10347
|
+
simo-2.0.2.dist-info/METADATA,sha256=svTddp9-mP3qTEeGmU9RQ__HdbwqgbY6ivmcGiRa4xg,1669
|
|
10348
|
+
simo-2.0.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
10349
|
+
simo-2.0.2.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10350
|
+
simo-2.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|