simo 2.4.1__py3-none-any.whl → 2.5.1__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/backups/__pycache__/admin.cpython-38.pyc +0 -0
- simo/backups/__pycache__/models.cpython-38.pyc +0 -0
- simo/backups/__pycache__/tasks.cpython-38.pyc +0 -0
- simo/backups/admin.py +10 -13
- simo/backups/migrations/0003_alter_backuplog_options_alter_backup_size.py +22 -0
- simo/backups/migrations/0004_alter_backup_options_alter_backuplog_options_and_more.py +29 -0
- simo/backups/migrations/__pycache__/0003_alter_backuplog_options_alter_backup_size.cpython-38.pyc +0 -0
- simo/backups/migrations/__pycache__/0004_alter_backup_options_alter_backuplog_options_and_more.cpython-38.pyc +0 -0
- simo/backups/models.py +1 -7
- simo/backups/tasks.py +221 -145
- simo/core/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/__pycache__/api.cpython-38.pyc +0 -0
- simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/core/__pycache__/events.cpython-38.pyc +0 -0
- simo/core/__pycache__/forms.cpython-38.pyc +0 -0
- simo/core/__pycache__/middleware.cpython-38.pyc +0 -0
- simo/core/__pycache__/models.cpython-38.pyc +0 -0
- simo/core/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
- simo/core/admin.py +4 -4
- simo/core/api.py +20 -4
- simo/core/app_widgets.py +5 -0
- simo/core/controllers.py +2 -2
- simo/core/events.py +2 -0
- simo/core/forms.py +2 -0
- simo/core/management/commands/gateways_manager.py +0 -3
- simo/core/middleware.py +7 -1
- simo/core/migrations/0042_alter_instance_timezone.py +18 -0
- simo/core/migrations/__pycache__/0042_alter_instance_timezone.cpython-38.pyc +0 -0
- simo/core/models.py +26 -6
- simo/core/serializers.py +17 -17
- simo/core/tasks.py +10 -7
- simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/models.cpython-38.pyc +0 -0
- simo/fleet/controllers.py +86 -22
- simo/fleet/forms.py +224 -185
- simo/fleet/migrations/0038_alter_colonel_type.py +18 -0
- simo/fleet/migrations/0039_auto_20241016_1047.py +28 -0
- simo/fleet/migrations/0040_alter_colonel_pwm_frequency.py +18 -0
- simo/fleet/migrations/__pycache__/0038_alter_colonel_type.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0039_auto_20241016_1047.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0040_alter_colonel_pwm_frequency.cpython-38.pyc +0 -0
- simo/fleet/models.py +2 -2
- 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/__pycache__/models.cpython-38.pyc +0 -0
- simo/generic/controllers.py +41 -2
- simo/generic/forms.py +71 -7
- simo/generic/models.py +0 -1
- simo/generic/scripting/__init__.py +16 -0
- simo/generic/scripting/__pycache__/__init__.cpython-38.pyc +0 -0
- simo/generic/scripting/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/generic/scripting/helpers.py +35 -0
- simo/generic/scripting/serializers.py +77 -0
- simo/generic/templates/admin/controller_widgets/weather_forecast.html +2 -2
- simo/notifications/__pycache__/models.cpython-38.pyc +0 -0
- simo/notifications/__pycache__/utils.cpython-38.pyc +0 -0
- simo/notifications/utils.py +30 -12
- simo/scripting.py +2 -2
- simo/users/__pycache__/api.cpython-38.pyc +0 -0
- simo/users/__pycache__/managers.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/users/__pycache__/utils.cpython-38.pyc +0 -0
- simo/users/api.py +36 -7
- simo/users/managers.py +5 -1
- simo/users/migrations/0033_alter_user_ssh_key.py +18 -0
- simo/users/migrations/0034_instanceuser_last_seen_location_and_more.py +24 -0
- simo/users/migrations/__pycache__/0033_alter_user_ssh_key.cpython-38.pyc +0 -0
- simo/users/migrations/__pycache__/0034_instanceuser_last_seen_location_and_more.cpython-38.pyc +0 -0
- simo/users/models.py +37 -32
- simo/users/serializers.py +11 -8
- simo/users/utils.py +14 -3
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/METADATA +1 -1
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/RECORD +82 -59
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/WHEEL +1 -1
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/LICENSE.md +0 -0
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/entry_points.txt +0 -0
- {simo-2.4.1.dist-info → simo-2.5.1.dist-info}/top_level.txt +0 -0
simo/core/api.py
CHANGED
|
@@ -167,6 +167,12 @@ def get_components_queryset(instance, user):
|
|
|
167
167
|
).values('id').first()
|
|
168
168
|
if main_alarm_group:
|
|
169
169
|
c_ids.add(main_alarm_group['id'])
|
|
170
|
+
state = Component.objects.filter(
|
|
171
|
+
zone__instance=instance,
|
|
172
|
+
base_type='state-select', config__is_main=True
|
|
173
|
+
).values('id').first()
|
|
174
|
+
if state:
|
|
175
|
+
c_ids.add(state['id'])
|
|
170
176
|
|
|
171
177
|
user_role = user.get_role(instance)
|
|
172
178
|
|
|
@@ -369,7 +375,7 @@ class ComponentHistoryViewSet(InstanceMixin, viewsets.ReadOnlyModelViewSet):
|
|
|
369
375
|
if not component.controller:
|
|
370
376
|
return
|
|
371
377
|
|
|
372
|
-
history_display_example = component.controller.
|
|
378
|
+
history_display_example = component.controller._history_display([component.value])
|
|
373
379
|
if not history_display_example:
|
|
374
380
|
return None
|
|
375
381
|
|
|
@@ -393,9 +399,9 @@ class ComponentHistoryViewSet(InstanceMixin, viewsets.ReadOnlyModelViewSet):
|
|
|
393
399
|
values = []
|
|
394
400
|
for item in history_items:
|
|
395
401
|
values.append(item.value)
|
|
396
|
-
val = component.controller.
|
|
402
|
+
val = component.controller._history_display(values)
|
|
397
403
|
else:
|
|
398
|
-
val = component.controller.
|
|
404
|
+
val = component.controller._history_display([])
|
|
399
405
|
|
|
400
406
|
if not val:
|
|
401
407
|
val = prev_val
|
|
@@ -425,7 +431,7 @@ class ComponentHistoryViewSet(InstanceMixin, viewsets.ReadOnlyModelViewSet):
|
|
|
425
431
|
component=component, date__lt=start_from, type='value'
|
|
426
432
|
).order_by('date').last()
|
|
427
433
|
if last_event:
|
|
428
|
-
prev_val = component.controller.
|
|
434
|
+
prev_val = component.controller._history_display([last_event.value])
|
|
429
435
|
else:
|
|
430
436
|
prev_val = history_display_example
|
|
431
437
|
|
|
@@ -544,6 +550,15 @@ class SettingsViewSet(InstanceMixin, viewsets.GenericViewSet):
|
|
|
544
550
|
if main_alarm_group:
|
|
545
551
|
main_alarm_group_id = main_alarm_group.id
|
|
546
552
|
|
|
553
|
+
main_state = Component.objects.filter(
|
|
554
|
+
zone__instance=self.instance,
|
|
555
|
+
base_type='state-select', config__is_main=True
|
|
556
|
+
).first()
|
|
557
|
+
if main_state:
|
|
558
|
+
main_state = main_state.id
|
|
559
|
+
else:
|
|
560
|
+
main_state = None
|
|
561
|
+
|
|
547
562
|
return RESTResponse({
|
|
548
563
|
'hub_uid': dynamic_settings['core__hub_uid'],
|
|
549
564
|
'instance_name': self.instance.name,
|
|
@@ -553,6 +568,7 @@ class SettingsViewSet(InstanceMixin, viewsets.GenericViewSet):
|
|
|
553
568
|
'last_event': last_event,
|
|
554
569
|
'weather_forecast': wf_comp_id,
|
|
555
570
|
'main_alarm_group': main_alarm_group_id,
|
|
571
|
+
'main_state': main_state,
|
|
556
572
|
# TODO: Remove these two when the app is updated for everybody.
|
|
557
573
|
'remote_http': dynamic_settings['core__remote_http'],
|
|
558
574
|
'local_http': 'https://%s' % get_self_ip(),
|
simo/core/app_widgets.py
CHANGED
simo/core/controllers.py
CHANGED
|
@@ -302,7 +302,7 @@ class ControllerBase(ABC):
|
|
|
302
302
|
from .models import Component
|
|
303
303
|
Component.objects.bulk_send(bulk_send_map)
|
|
304
304
|
|
|
305
|
-
def
|
|
305
|
+
def _history_display(self, values):
|
|
306
306
|
assert type(values) in (list, tuple)
|
|
307
307
|
|
|
308
308
|
if type(self.component.value) in (int, float):
|
|
@@ -445,7 +445,7 @@ class MultiSensor(ControllerBase):
|
|
|
445
445
|
))
|
|
446
446
|
return value
|
|
447
447
|
|
|
448
|
-
def
|
|
448
|
+
def _history_display(self, values):
|
|
449
449
|
assert type(values) in (list, tuple)
|
|
450
450
|
|
|
451
451
|
vectors = []
|
simo/core/events.py
CHANGED
simo/core/forms.py
CHANGED
|
@@ -212,6 +212,8 @@ class ComponentAdminForm(forms.ModelForm):
|
|
|
212
212
|
controller_type = None
|
|
213
213
|
has_icon = True
|
|
214
214
|
has_alarm = True
|
|
215
|
+
# do not allow modification via app of these fields
|
|
216
|
+
app_exclude_fields = []
|
|
215
217
|
|
|
216
218
|
# fields that can be edited via SIMO.io app by instance owners.
|
|
217
219
|
# Users who have is_owner enabled on their user role.
|
simo/core/middleware.py
CHANGED
|
@@ -30,12 +30,18 @@ def get_current_instance(request=None):
|
|
|
30
30
|
if not instance and request and request.session.get('instance_id'):
|
|
31
31
|
from simo.core.models import Instance
|
|
32
32
|
instance = Instance.objects.filter(
|
|
33
|
-
id=request.session['instance_id']
|
|
33
|
+
id=request.session['instance_id'], is_active=True
|
|
34
34
|
).first()
|
|
35
35
|
if not instance:
|
|
36
36
|
del request.session['instance_id']
|
|
37
37
|
else:
|
|
38
38
|
introduce_instance(instance, request)
|
|
39
|
+
|
|
40
|
+
if not instance:
|
|
41
|
+
from .models import Instance
|
|
42
|
+
instance = Instance.objects.filter(is_active=True).first()
|
|
43
|
+
if instance:
|
|
44
|
+
introduce_instance(instance)
|
|
39
45
|
return instance
|
|
40
46
|
|
|
41
47
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-10-09 09:16
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('core', '0041_alter_instance_slug'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='instance',
|
|
15
|
+
name='timezone',
|
|
16
|
+
field=models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Asmera', 'Africa/Asmera'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Timbuktu', 'Africa/Timbuktu'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/ComodRivadavia', 'America/Argentina/ComodRivadavia'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Atka', 'America/Atka'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Buenos_Aires', 'America/Buenos_Aires'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Catamarca', 'America/Catamarca'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Ciudad_Juarez', 'America/Ciudad_Juarez'), ('America/Coral_Harbour', 'America/Coral_Harbour'), ('America/Cordoba', 'America/Cordoba'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Ensenada', 'America/Ensenada'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fort_Wayne', 'America/Fort_Wayne'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Indianapolis', 'America/Indianapolis'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Jujuy', 'America/Jujuy'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Knox_IN', 'America/Knox_IN'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Louisville', 'America/Louisville'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Mendoza', 'America/Mendoza'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montreal', 'America/Montreal'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Nuuk', 'America/Nuuk'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Acre', 'America/Porto_Acre'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Rosario', 'America/Rosario'), ('America/Santa_Isabel', 'America/Santa_Isabel'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Shiprock', 'America/Shiprock'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Virgin', 'America/Virgin'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/South_Pole', 'Antarctica/South_Pole'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Ashkhabad', 'Asia/Ashkhabad'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Calcutta', 'Asia/Calcutta'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Chongqing', 'Asia/Chongqing'), ('Asia/Chungking', 'Asia/Chungking'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Dacca', 'Asia/Dacca'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Harbin', 'Asia/Harbin'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Istanbul', 'Asia/Istanbul'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kashgar', 'Asia/Kashgar'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Katmandu', 'Asia/Katmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macao', 'Asia/Macao'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qostanay', 'Asia/Qostanay'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Rangoon', 'Asia/Rangoon'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Saigon', 'Asia/Saigon'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Tel_Aviv', 'Asia/Tel_Aviv'), ('Asia/Thimbu', 'Asia/Thimbu'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ujung_Pandang', 'Asia/Ujung_Pandang'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Ulan_Bator', 'Asia/Ulan_Bator'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faeroe', 'Atlantic/Faeroe'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Jan_Mayen', 'Atlantic/Jan_Mayen'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/ACT', 'Australia/ACT'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Canberra', 'Australia/Canberra'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/LHI', 'Australia/LHI'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/NSW', 'Australia/NSW'), ('Australia/North', 'Australia/North'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Queensland', 'Australia/Queensland'), ('Australia/South', 'Australia/South'), ('Australia/Sydney', 'Australia/Sydney'), ('Australia/Tasmania', 'Australia/Tasmania'), ('Australia/Victoria', 'Australia/Victoria'), ('Australia/West', 'Australia/West'), ('Australia/Yancowinna', 'Australia/Yancowinna'), ('Brazil/Acre', 'Brazil/Acre'), ('Brazil/DeNoronha', 'Brazil/DeNoronha'), ('Brazil/East', 'Brazil/East'), ('Brazil/West', 'Brazil/West'), ('CET', 'CET'), ('CST6CDT', 'CST6CDT'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Canada/Saskatchewan', 'Canada/Saskatchewan'), ('Canada/Yukon', 'Canada/Yukon'), ('Chile/Continental', 'Chile/Continental'), ('Chile/EasterIsland', 'Chile/EasterIsland'), ('Cuba', 'Cuba'), ('EET', 'EET'), ('EST', 'EST'), ('EST5EDT', 'EST5EDT'), ('Egypt', 'Egypt'), ('Eire', 'Eire'), ('Etc/GMT', 'Etc/GMT'), ('Etc/GMT+0', 'Etc/GMT+0'), ('Etc/GMT+1', 'Etc/GMT+1'), ('Etc/GMT+10', 'Etc/GMT+10'), ('Etc/GMT+11', 'Etc/GMT+11'), ('Etc/GMT+12', 'Etc/GMT+12'), ('Etc/GMT+2', 'Etc/GMT+2'), ('Etc/GMT+3', 'Etc/GMT+3'), ('Etc/GMT+4', 'Etc/GMT+4'), ('Etc/GMT+5', 'Etc/GMT+5'), ('Etc/GMT+6', 'Etc/GMT+6'), ('Etc/GMT+7', 'Etc/GMT+7'), ('Etc/GMT+8', 'Etc/GMT+8'), ('Etc/GMT+9', 'Etc/GMT+9'), ('Etc/GMT-0', 'Etc/GMT-0'), ('Etc/GMT-1', 'Etc/GMT-1'), ('Etc/GMT-10', 'Etc/GMT-10'), ('Etc/GMT-11', 'Etc/GMT-11'), ('Etc/GMT-12', 'Etc/GMT-12'), ('Etc/GMT-13', 'Etc/GMT-13'), ('Etc/GMT-14', 'Etc/GMT-14'), ('Etc/GMT-2', 'Etc/GMT-2'), ('Etc/GMT-3', 'Etc/GMT-3'), ('Etc/GMT-4', 'Etc/GMT-4'), ('Etc/GMT-5', 'Etc/GMT-5'), ('Etc/GMT-6', 'Etc/GMT-6'), ('Etc/GMT-7', 'Etc/GMT-7'), ('Etc/GMT-8', 'Etc/GMT-8'), ('Etc/GMT-9', 'Etc/GMT-9'), ('Etc/GMT0', 'Etc/GMT0'), ('Etc/Greenwich', 'Etc/Greenwich'), ('Etc/UCT', 'Etc/UCT'), ('Etc/UTC', 'Etc/UTC'), ('Etc/Universal', 'Etc/Universal'), ('Etc/Zulu', 'Etc/Zulu'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belfast', 'Europe/Belfast'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Kyiv', 'Europe/Kyiv'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Nicosia', 'Europe/Nicosia'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Tiraspol', 'Europe/Tiraspol'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GB', 'GB'), ('GB-Eire', 'GB-Eire'), ('GMT', 'GMT'), ('GMT+0', 'GMT+0'), ('GMT-0', 'GMT-0'), ('GMT0', 'GMT0'), ('Greenwich', 'Greenwich'), ('HST', 'HST'), ('Hongkong', 'Hongkong'), ('Iceland', 'Iceland'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Iran', 'Iran'), ('Israel', 'Israel'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Kwajalein', 'Kwajalein'), ('Libya', 'Libya'), ('MET', 'MET'), ('MST', 'MST'), ('MST7MDT', 'MST7MDT'), ('Mexico/BajaNorte', 'Mexico/BajaNorte'), ('Mexico/BajaSur', 'Mexico/BajaSur'), ('Mexico/General', 'Mexico/General'), ('NZ', 'NZ'), ('NZ-CHAT', 'NZ-CHAT'), ('Navajo', 'Navajo'), ('PRC', 'PRC'), ('PST8PDT', 'PST8PDT'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Johnston', 'Pacific/Johnston'), ('Pacific/Kanton', 'Pacific/Kanton'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Ponape', 'Pacific/Ponape'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Samoa', 'Pacific/Samoa'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Truk', 'Pacific/Truk'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('Pacific/Yap', 'Pacific/Yap'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('ROC', 'ROC'), ('ROK', 'ROK'), ('Singapore', 'Singapore'), ('Turkey', 'Turkey'), ('UCT', 'UCT'), ('US/Alaska', 'US/Alaska'), ('US/Aleutian', 'US/Aleutian'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/East-Indiana', 'US/East-Indiana'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Indiana-Starke', 'US/Indiana-Starke'), ('US/Michigan', 'US/Michigan'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('US/Samoa', 'US/Samoa'), ('UTC', 'UTC'), ('Universal', 'Universal'), ('W-SU', 'W-SU'), ('WET', 'WET'), ('Zulu', 'Zulu')], db_index=True, max_length=50),
|
|
17
|
+
),
|
|
18
|
+
]
|
simo/core/models.py
CHANGED
|
@@ -406,8 +406,8 @@ def is_in_alarm(self):
|
|
|
406
406
|
|
|
407
407
|
_controller_initiated = False
|
|
408
408
|
|
|
409
|
-
|
|
410
|
-
|
|
409
|
+
|
|
410
|
+
|
|
411
411
|
_obj_ct_id = 0
|
|
412
412
|
|
|
413
413
|
class Meta:
|
|
@@ -517,11 +517,13 @@ def is_in_alarm(self):
|
|
|
517
517
|
actor.last_action = timezone.now()
|
|
518
518
|
actor.save()
|
|
519
519
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
['value', 'arm_status', 'battery_level', 'alive', 'meta']
|
|
523
|
-
):
|
|
520
|
+
changing_fields = ['value', 'arm_status', 'battery_level', 'alive', 'meta']
|
|
521
|
+
if any(f in dirty_fields for f in changing_fields):
|
|
524
522
|
self.last_change = timezone.now()
|
|
523
|
+
if 'update_fields' in kwargs \
|
|
524
|
+
and 'last_change' not in kwargs['update_fields']:
|
|
525
|
+
kwargs['update_fields'].append('last_change')
|
|
526
|
+
|
|
525
527
|
|
|
526
528
|
modifying_fields = (
|
|
527
529
|
'name', 'icon', 'zone', 'category', 'config', 'meta',
|
|
@@ -529,6 +531,9 @@ def is_in_alarm(self):
|
|
|
529
531
|
)
|
|
530
532
|
if any(f in dirty_fields for f in modifying_fields):
|
|
531
533
|
self.last_modified = timezone.now()
|
|
534
|
+
if 'update_fields' in kwargs \
|
|
535
|
+
and 'last_modified' not in kwargs['update_fields']:
|
|
536
|
+
kwargs['update_fields'].append('last_modified')
|
|
532
537
|
|
|
533
538
|
obj = super().save(*args, **kwargs)
|
|
534
539
|
|
|
@@ -581,6 +586,21 @@ def is_in_alarm(self):
|
|
|
581
586
|
return False
|
|
582
587
|
return perm.write
|
|
583
588
|
|
|
589
|
+
def get_controller_methods(self):
|
|
590
|
+
c_methods = []
|
|
591
|
+
for m in inspect.getmembers(
|
|
592
|
+
self.controller, predicate=inspect.ismethod
|
|
593
|
+
):
|
|
594
|
+
method = m[0]
|
|
595
|
+
if method.startswith('_'):
|
|
596
|
+
continue
|
|
597
|
+
if method in ('info', 'set'):
|
|
598
|
+
continue
|
|
599
|
+
c_methods.append(method)
|
|
600
|
+
if self.alarm_category:
|
|
601
|
+
c_methods.extend(['arm', 'disarm'])
|
|
602
|
+
return c_methods
|
|
603
|
+
|
|
584
604
|
|
|
585
605
|
class ComponentHistory(models.Model):
|
|
586
606
|
component = models.ForeignKey(
|
simo/core/serializers.py
CHANGED
|
@@ -27,6 +27,8 @@ from .forms import ComponentAdminForm
|
|
|
27
27
|
from .models import Category, Zone, Icon, ComponentHistory
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
|
|
31
|
+
|
|
30
32
|
class TimestampField(serializers.Field):
|
|
31
33
|
|
|
32
34
|
def to_representation(self, value):
|
|
@@ -318,7 +320,7 @@ class ComponentSerializer(FormSerializer):
|
|
|
318
320
|
form_field = form[field_name]
|
|
319
321
|
|
|
320
322
|
cls = form_field.field.__class__
|
|
321
|
-
if
|
|
323
|
+
if isinstance(form_field.field.widget, forms.Textarea):
|
|
322
324
|
serializer_field_class = TextAreaSerializerField
|
|
323
325
|
else:
|
|
324
326
|
try:
|
|
@@ -416,16 +418,19 @@ class ComponentSerializer(FormSerializer):
|
|
|
416
418
|
controller_uid=controller_uid, instance=instance,
|
|
417
419
|
**kwargs
|
|
418
420
|
)
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
421
|
+
|
|
422
|
+
user_role = self.context['request'].user.get_role(
|
|
423
|
+
self.context['instance']
|
|
424
|
+
)
|
|
425
|
+
for field_name in list(form.fields.keys()):
|
|
426
|
+
if field_name in form.app_exclude_fields:
|
|
427
|
+
del form.fields[field_name]
|
|
428
|
+
continue
|
|
429
|
+
if field_name in form.basic_fields:
|
|
430
|
+
continue
|
|
431
|
+
if self.context['request'].user.is_master or user_role.is_superuser:
|
|
432
|
+
continue
|
|
433
|
+
del form.fields[field_name]
|
|
429
434
|
|
|
430
435
|
if form_key is not None:
|
|
431
436
|
self.context['forms'][form_key] = form
|
|
@@ -492,12 +497,7 @@ class ComponentSerializer(FormSerializer):
|
|
|
492
497
|
raise serializers.ValidationError(form.errors)
|
|
493
498
|
|
|
494
499
|
def get_controller_methods(self, obj):
|
|
495
|
-
|
|
496
|
-
obj.controller, predicate=inspect.ismethod
|
|
497
|
-
) if not m[0].startswith('_')]
|
|
498
|
-
if obj.alarm_category:
|
|
499
|
-
c_methods.extend(['arm', 'disarm'])
|
|
500
|
-
return c_methods
|
|
500
|
+
return obj.get_controller_methods()
|
|
501
501
|
|
|
502
502
|
def get_info(self, obj):
|
|
503
503
|
if obj.controller:
|
simo/core/tasks.py
CHANGED
|
@@ -211,7 +211,11 @@ def sync_with_remote():
|
|
|
211
211
|
).first()
|
|
212
212
|
if weather_component:
|
|
213
213
|
weather_component.track_history = False
|
|
214
|
-
weather_component.controller.set(
|
|
214
|
+
weather_component.controller.set(
|
|
215
|
+
weather_forecast.pop('current', None)
|
|
216
|
+
)
|
|
217
|
+
weather_component.meta['forecast'] = weather_forecast
|
|
218
|
+
weather_component.save()
|
|
215
219
|
|
|
216
220
|
for email, options in users_data.items():
|
|
217
221
|
|
|
@@ -380,15 +384,14 @@ def low_battery_notifications():
|
|
|
380
384
|
zone__instance=instance,
|
|
381
385
|
battery_level__isnull=False, battery_level__lt=20
|
|
382
386
|
):
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if users:
|
|
387
|
+
iusers = comp.zone.instance.instance_users.filter(
|
|
388
|
+
is_active=True, role__is_owner=True
|
|
389
|
+
)
|
|
390
|
+
if iusers:
|
|
388
391
|
notify_users(
|
|
389
392
|
comp.zone.instance, 'warning',
|
|
390
393
|
f"Low battery ({comp.battery_level}%) on {comp}",
|
|
391
|
-
component=comp,
|
|
394
|
+
component=comp, instance_users=iusers
|
|
392
395
|
)
|
|
393
396
|
|
|
394
397
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/fleet/controllers.py
CHANGED
|
@@ -10,8 +10,7 @@ from simo.core.controllers import (
|
|
|
10
10
|
Switch as BaseSwitch, Dimmer as BaseDimmer,
|
|
11
11
|
MultiSensor as BaseMultiSensor, RGBWLight as BaseRGBWLight
|
|
12
12
|
)
|
|
13
|
-
from simo.
|
|
14
|
-
from simo.core.app_widgets import NumericSensorWidget
|
|
13
|
+
from simo.core.app_widgets import NumericSensorWidget, AirQualityWidget
|
|
15
14
|
from simo.core.controllers import Lock, ControllerBase, SingleSwitchWidget
|
|
16
15
|
from simo.core.utils.helpers import heat_index
|
|
17
16
|
from simo.core.utils.serialization import (
|
|
@@ -23,7 +22,7 @@ from .gateways import FleetGatewayHandler
|
|
|
23
22
|
from .forms import (
|
|
24
23
|
ColonelPinChoiceField,
|
|
25
24
|
ColonelBinarySensorConfigForm, ColonelButtonConfigForm,
|
|
26
|
-
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm,
|
|
25
|
+
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm, DCDriverConfigForm,
|
|
27
26
|
ColonelNumericSensorConfigForm, ColonelRGBLightConfigForm,
|
|
28
27
|
ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
|
|
29
28
|
BME680SensorConfigForm, MPC9808SensorConfigForm, ENS160SensorConfigForm,
|
|
@@ -239,6 +238,7 @@ class ENS160AirQualitySensor(FleeDeviceMixin, BaseMultiSensor):
|
|
|
239
238
|
gateway_class = FleetGatewayHandler
|
|
240
239
|
config_form = ENS160SensorConfigForm
|
|
241
240
|
name = "ENS160 Air Quality Sensor (I2C)"
|
|
241
|
+
app_widget = AirQualityWidget
|
|
242
242
|
|
|
243
243
|
default_value = [
|
|
244
244
|
["CO2", 0, "ppm"],
|
|
@@ -386,42 +386,87 @@ class PWMOutput(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
386
386
|
value = conf.get('min', 0)
|
|
387
387
|
|
|
388
388
|
if value >= conf.get('max', 100):
|
|
389
|
-
|
|
390
|
-
pwm_value = 0
|
|
391
|
-
else:
|
|
392
|
-
pwm_value = 1023
|
|
389
|
+
pwm_value = 0
|
|
393
390
|
elif value <= conf.get('min', 100):
|
|
394
|
-
|
|
395
|
-
pwm_value = 1023
|
|
396
|
-
else:
|
|
397
|
-
pwm_value = 0
|
|
391
|
+
pwm_value = 1023
|
|
398
392
|
else:
|
|
399
393
|
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
400
394
|
val_relative = value / val_amplitude
|
|
401
|
-
pwm_amplitude = conf.get('duty_max', 1023) - conf.get('duty_min', 0.0)
|
|
402
|
-
pwm_value = conf.get('duty_min', 0.0) + pwm_amplitude * val_relative
|
|
403
395
|
|
|
404
|
-
|
|
405
|
-
|
|
396
|
+
duty_max = 1023 - (conf.get('device_min', 0) * 0.01 * 1023)
|
|
397
|
+
duty_min = 1023 - conf.get('device_max', 100) * 0.01 * 1023
|
|
398
|
+
|
|
399
|
+
pwm_amplitude = duty_max - duty_min
|
|
400
|
+
pwm_value = duty_min + pwm_amplitude * val_relative
|
|
401
|
+
|
|
402
|
+
pwm_value = duty_max - pwm_value + duty_min
|
|
406
403
|
|
|
407
404
|
return pwm_value
|
|
408
405
|
|
|
409
406
|
def _prepare_for_set(self, pwm_value):
|
|
410
407
|
conf = self.component.config
|
|
411
|
-
|
|
408
|
+
duty_max = 1023 - (conf.get('device_min', 0) * 0.01 * 1023)
|
|
409
|
+
duty_min = 1023 - conf.get('device_max', 100) * 0.01 * 1023
|
|
410
|
+
|
|
411
|
+
if pwm_value > duty_max:
|
|
412
412
|
value = conf.get('max', 100)
|
|
413
|
-
elif pwm_value <
|
|
413
|
+
elif pwm_value < duty_min:
|
|
414
414
|
value = conf.get('min', 0)
|
|
415
415
|
else:
|
|
416
|
-
pwm_amplitude =
|
|
417
|
-
relative_value = (pwm_value -
|
|
416
|
+
pwm_amplitude =duty_max - duty_min
|
|
417
|
+
relative_value = (pwm_value - duty_min) / pwm_amplitude
|
|
418
418
|
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
419
419
|
value = conf.get('min', 0) + val_amplitude * relative_value
|
|
420
420
|
|
|
421
|
-
|
|
422
|
-
value = conf.get('max', 100) - value + conf.get('min', 0)
|
|
421
|
+
value = conf.get('max', 100) - value + conf.get('min', 0)
|
|
423
422
|
|
|
424
|
-
return value
|
|
423
|
+
return round(value, 3)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class DCDriver(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
427
|
+
name = "0 - 24V DC Driver"
|
|
428
|
+
config_form = DCDriverConfigForm
|
|
429
|
+
default_value_units = 'V'
|
|
430
|
+
|
|
431
|
+
def _prepare_for_send(self, value):
|
|
432
|
+
conf = self.component.config
|
|
433
|
+
if value >= conf.get('max', 24):
|
|
434
|
+
value = conf.get('max', 24)
|
|
435
|
+
elif value < conf.get('min', 0):
|
|
436
|
+
value = conf.get('min', 0)
|
|
437
|
+
|
|
438
|
+
if value >= conf.get('max', 24):
|
|
439
|
+
pwm_value = 1023
|
|
440
|
+
elif value <= conf.get('min', 100):
|
|
441
|
+
pwm_value = 0
|
|
442
|
+
else:
|
|
443
|
+
val_amplitude = conf.get('max', 24) - conf.get('min', 0)
|
|
444
|
+
val_relative = value / val_amplitude
|
|
445
|
+
|
|
446
|
+
duty_max = conf.get('device_max', 24) / 24 * 1023
|
|
447
|
+
duty_min = conf.get('device_min', 0) / 24 * 1023
|
|
448
|
+
|
|
449
|
+
pwm_amplitude = duty_max - duty_min
|
|
450
|
+
pwm_value = duty_min + pwm_amplitude * val_relative
|
|
451
|
+
|
|
452
|
+
return pwm_value
|
|
453
|
+
|
|
454
|
+
def _prepare_for_set(self, pwm_value):
|
|
455
|
+
conf = self.component.config
|
|
456
|
+
duty_max = conf.get('device_max', 24) / 24 * 1023
|
|
457
|
+
duty_min = conf.get('device_min', 0) / 24 * 1023
|
|
458
|
+
|
|
459
|
+
if pwm_value > duty_max:
|
|
460
|
+
value = conf.get('max', 24)
|
|
461
|
+
elif pwm_value < duty_min:
|
|
462
|
+
value = conf.get('min', 0)
|
|
463
|
+
else:
|
|
464
|
+
pwm_amplitude = duty_max - duty_min
|
|
465
|
+
relative_value = (pwm_value - duty_min) / pwm_amplitude
|
|
466
|
+
val_amplitude = conf.get('max', 24) - conf.get('min', 0)
|
|
467
|
+
value = conf.get('min', 0) + val_amplitude * relative_value
|
|
468
|
+
|
|
469
|
+
return round(value, 3)
|
|
425
470
|
|
|
426
471
|
|
|
427
472
|
class RGBLight(FleeDeviceMixin, BasicOutputMixin, BaseRGBWLight):
|
|
@@ -460,6 +505,25 @@ class DualMotorValve(FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
460
505
|
|
|
461
506
|
self.component.save()
|
|
462
507
|
|
|
508
|
+
def _prepare_for_send(self, value):
|
|
509
|
+
conf = self.component.config
|
|
510
|
+
if value >= conf.get('max', 100):
|
|
511
|
+
value = conf.get('max', 100)
|
|
512
|
+
elif value < conf.get('min', 0):
|
|
513
|
+
value = conf.get('min', 0)
|
|
514
|
+
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
515
|
+
return ((value - conf.get('min', 0)) / val_amplitude) * 100
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def _prepare_for_set(self, value):
|
|
519
|
+
conf = self.component.config
|
|
520
|
+
if value > conf.get('max', 100):
|
|
521
|
+
value = conf.get('max', 100)
|
|
522
|
+
elif value < conf.get('min', 0.0):
|
|
523
|
+
value = conf.get('min', 0)
|
|
524
|
+
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
525
|
+
return conf.get('min', 0) + (value / 100) * val_amplitude
|
|
526
|
+
|
|
463
527
|
|
|
464
528
|
class Blinds(FleeDeviceMixin, BasicOutputMixin, GenericBlinds):
|
|
465
529
|
gateway_class = FleetGatewayHandler
|