simo 2.0.6__py3-none-any.whl → 2.0.7__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/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/__pycache__/api.cpython-38.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/core/__pycache__/forms.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/admin.py +4 -2
- simo/core/api.py +5 -3
- simo/core/controllers.py +1 -0
- simo/core/forms.py +1 -1
- simo/core/migrations/0030_alter_instance_timezone.py +18 -0
- simo/core/migrations/__pycache__/0030_alter_instance_timezone.cpython-38.pyc +0 -0
- simo/core/models.py +1 -0
- simo/core/serializers.py +1 -1
- simo/core/utils/__pycache__/serialization.cpython-38.pyc +0 -0
- simo/core/utils/serialization.py +4 -2
- simo/fleet/__pycache__/admin.cpython-38.pyc +0 -0
- 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__/managers.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/admin.py +6 -6
- simo/fleet/auto_urls.py +4 -4
- simo/fleet/controllers.py +75 -2
- simo/fleet/forms.py +68 -33
- simo/fleet/gateways.py +7 -3
- simo/fleet/managers.py +4 -2
- simo/fleet/migrations/0032_auto_20240415_0736.py +33 -0
- simo/fleet/migrations/0033_auto_20240415_0736.py +28 -0
- simo/fleet/migrations/__pycache__/0032_auto_20240415_0736.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0033_auto_20240415_0736.cpython-38.pyc +0 -0
- simo/fleet/models.py +82 -14
- simo/fleet/socket_consumers.py +19 -12
- simo/fleet/utils.py +6 -1
- simo/fleet/views.py +10 -9
- {simo-2.0.6.dist-info → simo-2.0.7.dist-info}/METADATA +1 -1
- {simo-2.0.6.dist-info → simo-2.0.7.dist-info}/RECORD +45 -39
- {simo-2.0.6.dist-info → simo-2.0.7.dist-info}/LICENSE.md +0 -0
- {simo-2.0.6.dist-info → simo-2.0.7.dist-info}/WHEEL +0 -0
- {simo-2.0.6.dist-info → simo-2.0.7.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/core/admin.py
CHANGED
|
@@ -322,7 +322,7 @@ class ComponentAdmin(admin.ModelAdmin):
|
|
|
322
322
|
if request.session.get('add_comp_type'):
|
|
323
323
|
try:
|
|
324
324
|
controller_cls = CONTROLLERS_BY_GATEWAY.get(
|
|
325
|
-
gateway, {}
|
|
325
|
+
gateway.type, {}
|
|
326
326
|
)[request.session['add_comp_type']]
|
|
327
327
|
except:
|
|
328
328
|
request.session.pop('add_comp_type')
|
|
@@ -355,6 +355,7 @@ class ComponentAdmin(admin.ModelAdmin):
|
|
|
355
355
|
pop_fields_from_form(ctx['form'])
|
|
356
356
|
if ctx['form'].is_valid():
|
|
357
357
|
if ctx['form'].controller.is_discoverable:
|
|
358
|
+
print("INIT DISCOVERY!!!")
|
|
358
359
|
ctx['form'].controller.init_discovery(
|
|
359
360
|
ctx['form'].cleaned_data
|
|
360
361
|
)
|
|
@@ -393,6 +394,7 @@ class ComponentAdmin(admin.ModelAdmin):
|
|
|
393
394
|
if ctx['form'].is_valid():
|
|
394
395
|
request.session['add_comp_type'] = \
|
|
395
396
|
ctx['form'].cleaned_data['controller_type']
|
|
397
|
+
print("Session controller type: ", request.session['add_comp_type'])
|
|
396
398
|
return redirect(request.path)
|
|
397
399
|
|
|
398
400
|
else:
|
|
@@ -429,7 +431,7 @@ class ComponentAdmin(admin.ModelAdmin):
|
|
|
429
431
|
if obj:
|
|
430
432
|
try:
|
|
431
433
|
self.form = CONTROLLERS_BY_GATEWAY.get(
|
|
432
|
-
obj.gateway, {}
|
|
434
|
+
obj.gateway.type, {}
|
|
433
435
|
)[obj.controller_uid].config_form
|
|
434
436
|
except KeyError:
|
|
435
437
|
pass
|
simo/core/api.py
CHANGED
|
@@ -62,7 +62,7 @@ class IconViewSet(viewsets.ReadOnlyModelViewSet):
|
|
|
62
62
|
if 'q' in self.request.GET:
|
|
63
63
|
queryset = search_queryset(
|
|
64
64
|
queryset, self.request.GET['q'], ['slug', 'keywords']
|
|
65
|
-
)[:
|
|
65
|
+
)[:25]
|
|
66
66
|
return queryset
|
|
67
67
|
|
|
68
68
|
def get_view_name(self):
|
|
@@ -592,7 +592,8 @@ class ControllerTypes(InstanceMixin, viewsets.GenericViewSet):
|
|
|
592
592
|
data[cls.gateway_class.name].append({
|
|
593
593
|
'uid': uid,
|
|
594
594
|
'name': cls.name,
|
|
595
|
-
'is_discoverable': cls.is_discoverable
|
|
595
|
+
'is_discoverable': cls.is_discoverable,
|
|
596
|
+
'manual_add': cls.manual_add
|
|
596
597
|
})
|
|
597
598
|
|
|
598
599
|
return RESTResponse(data)
|
|
@@ -603,7 +604,6 @@ class RunningDiscoveries(InstanceMixin, viewsets.GenericViewSet):
|
|
|
603
604
|
basename = 'discoveries'
|
|
604
605
|
queryset = []
|
|
605
606
|
|
|
606
|
-
|
|
607
607
|
def get_permissions(self):
|
|
608
608
|
permissions = super().get_permissions()
|
|
609
609
|
permissions.append(IsInstanceSuperuser())
|
|
@@ -612,6 +612,8 @@ class RunningDiscoveries(InstanceMixin, viewsets.GenericViewSet):
|
|
|
612
612
|
def get_data(self, gateways):
|
|
613
613
|
data = []
|
|
614
614
|
for gateway in gateways:
|
|
615
|
+
gateway.discovery['last_check'] = time.time()
|
|
616
|
+
gateway.save(update_fields=['discovery'])
|
|
615
617
|
data.append({
|
|
616
618
|
'gateway': gateway.id,
|
|
617
619
|
'start': gateway.discovery['start'],
|
simo/core/controllers.py
CHANGED
simo/core/forms.py
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 3.2.9 on 2024-04-15 11:08
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('core', '0029_auto_20240229_1331'),
|
|
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/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/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
|
@@ -278,6 +278,7 @@ class Gateway(DirtyFieldsMixin, models.Model, SimoAdminMixin):
|
|
|
278
278
|
started_with=self.discovery['init_data'], data=data
|
|
279
279
|
)
|
|
280
280
|
if result:
|
|
281
|
+
self.refresh_from_db()
|
|
281
282
|
if not isinstance(result, dict) and isinstance(result, Iterable):
|
|
282
283
|
for res in result:
|
|
283
284
|
if isinstance(res, models.Model):
|
simo/core/serializers.py
CHANGED
|
Binary file
|
simo/core/utils/serialization.py
CHANGED
|
@@ -21,14 +21,14 @@ def serialize_form_data(data):
|
|
|
21
21
|
serialized_data[field_name] = {
|
|
22
22
|
'model': 'many',
|
|
23
23
|
'val': json.loads(model_serializers.serialize(
|
|
24
|
-
'json', val
|
|
24
|
+
'json', val, fields=['pk']
|
|
25
25
|
))
|
|
26
26
|
}
|
|
27
27
|
else:
|
|
28
28
|
serialized_data[field_name] = {
|
|
29
29
|
'model': 'single',
|
|
30
30
|
'val': json.loads(model_serializers.serialize(
|
|
31
|
-
'json', [val]
|
|
31
|
+
'json', [val], fields=['pk']
|
|
32
32
|
))
|
|
33
33
|
}
|
|
34
34
|
else:
|
|
@@ -46,11 +46,13 @@ def deserialize_form_data(data):
|
|
|
46
46
|
if val['model'] == 'single':
|
|
47
47
|
for item in deserializer_generator:
|
|
48
48
|
deserialized_data[field_name] = item.object
|
|
49
|
+
deserialized_data[field_name].refresh_from_db()
|
|
49
50
|
break
|
|
50
51
|
else:
|
|
51
52
|
deserialized_data[field_name] = []
|
|
52
53
|
for item in deserializer_generator:
|
|
53
54
|
deserialized_data[field_name].append(item.object)
|
|
55
|
+
deserialized_data[field_name][-1].refresh_from_db()
|
|
54
56
|
else:
|
|
55
57
|
deserialized_data[field_name] = val
|
|
56
58
|
return deserialized_data
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/fleet/admin.py
CHANGED
|
@@ -5,14 +5,14 @@ from django.template.loader import render_to_string
|
|
|
5
5
|
from django.templatetags.static import static
|
|
6
6
|
from simo.core.models import Component
|
|
7
7
|
from simo.core.utils.admin import FormAction
|
|
8
|
-
from .models import Colonel,
|
|
9
|
-
from .forms import ColonelAdminForm, MoveColonelForm,
|
|
8
|
+
from .models import Colonel, Interface, ColonelPin
|
|
9
|
+
from .forms import ColonelAdminForm, MoveColonelForm, InterfaceAdminForm
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
13
|
-
model =
|
|
12
|
+
class InterfaceInline(admin.TabularInline):
|
|
13
|
+
model = Interface
|
|
14
14
|
extra = 0
|
|
15
|
-
form =
|
|
15
|
+
form = InterfaceAdminForm
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class ColonelPinsInline(admin.TabularInline):
|
|
@@ -71,7 +71,7 @@ class ColonelAdmin(admin.ModelAdmin):
|
|
|
71
71
|
'rebuild_occupied_pins'
|
|
72
72
|
)
|
|
73
73
|
|
|
74
|
-
inlines =
|
|
74
|
+
inlines = InterfaceInline, ColonelPinsInline
|
|
75
75
|
|
|
76
76
|
def get_queryset(self, request):
|
|
77
77
|
qs = super().get_queryset(request)
|
simo/fleet/auto_urls.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from django.urls import path, re_path
|
|
2
|
-
from django.views.generic import TemplateView
|
|
3
2
|
from .views import (
|
|
4
3
|
colonels_ping,
|
|
5
4
|
PinsSelectAutocomplete,
|
|
6
|
-
|
|
5
|
+
InterfaceSelectAutocomplete
|
|
7
6
|
)
|
|
8
7
|
|
|
9
8
|
urlpatterns = [
|
|
@@ -15,7 +14,8 @@ urlpatterns = [
|
|
|
15
14
|
PinsSelectAutocomplete.as_view(), name='autocomplete-colonel-pins'
|
|
16
15
|
),
|
|
17
16
|
path(
|
|
18
|
-
'autocomplete-colonel-
|
|
19
|
-
|
|
17
|
+
'autocomplete-colonel-interfaces',
|
|
18
|
+
InterfaceSelectAutocomplete.as_view(),
|
|
19
|
+
name='autocomplete-interfaces'
|
|
20
20
|
)
|
|
21
21
|
]
|
simo/fleet/controllers.py
CHANGED
|
@@ -24,7 +24,7 @@ from .forms import (
|
|
|
24
24
|
ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
|
|
25
25
|
BME680SensorConfigForm, MPC9808SensorConfigForm,
|
|
26
26
|
DualMotorValveForm, BlindsConfigForm, BurglarSmokeDetectorConfigForm,
|
|
27
|
-
TTLockConfigForm
|
|
27
|
+
TTLockConfigForm, DALIDeviceConfigForm
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
|
|
@@ -294,6 +294,7 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
294
294
|
@classmethod
|
|
295
295
|
def init_discovery(self, form_cleaned_data):
|
|
296
296
|
from simo.core.models import Gateway
|
|
297
|
+
print("INIT discovery form cleaned data: ", form_cleaned_data)
|
|
297
298
|
print("Serialized form: ", serialize_form_data(form_cleaned_data))
|
|
298
299
|
gateway = Gateway.objects.filter(type=self.gateway_class.uid).first()
|
|
299
300
|
gateway.start_discovery(
|
|
@@ -307,7 +308,7 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
307
308
|
|
|
308
309
|
@classmethod
|
|
309
310
|
def _process_discovery(cls, started_with, data):
|
|
310
|
-
if data['
|
|
311
|
+
if data['discovery-result'] == 'fail':
|
|
311
312
|
if data['result'] == 0:
|
|
312
313
|
return {'error': 'Internal Colonel error. See Colonel logs.'}
|
|
313
314
|
if data['result'] == 1:
|
|
@@ -348,6 +349,7 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
348
349
|
},
|
|
349
350
|
}
|
|
350
351
|
new_component.save()
|
|
352
|
+
new_component.gateway.finish_discovery()
|
|
351
353
|
GatewayObjectCommand(
|
|
352
354
|
new_component.gateway, Colonel(
|
|
353
355
|
id=new_component.config['colonel']
|
|
@@ -417,4 +419,75 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
417
419
|
).publish()
|
|
418
420
|
|
|
419
421
|
|
|
422
|
+
class DALIDevice(FleeDeviceMixin):
|
|
423
|
+
gateway_class = FleetGatewayHandler
|
|
424
|
+
config_form = DALIDeviceConfigForm
|
|
425
|
+
discovery_msg = _("Please hook up your new DALI device to your DALI bus.")
|
|
426
|
+
|
|
427
|
+
@classmethod
|
|
428
|
+
def init_discovery(self, form_cleaned_data):
|
|
429
|
+
from simo.core.models import Gateway
|
|
430
|
+
gateway = Gateway.objects.filter(type=self.gateway_class.uid).first()
|
|
431
|
+
gateway.start_discovery(
|
|
432
|
+
self.uid, serialize_form_data(form_cleaned_data),
|
|
433
|
+
timeout=60
|
|
434
|
+
)
|
|
435
|
+
GatewayObjectCommand(
|
|
436
|
+
gateway, form_cleaned_data['colonel'],
|
|
437
|
+
command=f'discover-dali',
|
|
438
|
+
interface=form_cleaned_data['interface'].no
|
|
439
|
+
).publish()
|
|
440
|
+
|
|
441
|
+
@classmethod
|
|
442
|
+
def _process_discovery(cls, started_with, data):
|
|
443
|
+
started_with = deserialize_form_data(started_with)
|
|
444
|
+
form = TTLockConfigForm(controller_uid=cls.uid, data=started_with)
|
|
445
|
+
|
|
446
|
+
if form.is_valid():
|
|
447
|
+
new_component = form.save()
|
|
448
|
+
new_component.config.update(data.get('result', {}).get('config'))
|
|
449
|
+
new_component.meta['finalization_data'] = {
|
|
450
|
+
'temp_id': data['result']['id'],
|
|
451
|
+
'permanent_id': new_component.id,
|
|
452
|
+
'config': {
|
|
453
|
+
'type': cls.uid.split('.')[-1],
|
|
454
|
+
'config': new_component.config,
|
|
455
|
+
'val': False,
|
|
456
|
+
},
|
|
457
|
+
}
|
|
458
|
+
new_component.save()
|
|
459
|
+
new_component.gateway.finish_discovery()
|
|
460
|
+
GatewayObjectCommand(
|
|
461
|
+
new_component.gateway, Colonel(
|
|
462
|
+
id=new_component.config['colonel']
|
|
463
|
+
), command='finalize',
|
|
464
|
+
data=new_component.meta['finalization_data'],
|
|
465
|
+
).publish()
|
|
466
|
+
return [new_component]
|
|
467
|
+
|
|
468
|
+
# Literally impossible, but just in case...
|
|
469
|
+
return {'error': 'INVALID INITIAL DISCOVERY FORM!'}
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
class DALIGear(DALIDevice):
|
|
473
|
+
|
|
474
|
+
def _send_to_device(self, value):
|
|
475
|
+
GatewayObjectCommand(
|
|
476
|
+
self.component.gateway,
|
|
477
|
+
Colonel(id=self.component.config['colonel']),
|
|
478
|
+
set_val=value,
|
|
479
|
+
component_id=self.component.id,
|
|
480
|
+
).publish()
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
class DALILamp(DALIGear, BaseSwitch):
|
|
484
|
+
manual_add = False
|
|
485
|
+
name = 'DALI Lamp'
|
|
486
|
+
discovery_msg = _("Please hook up your new DALI device to your DALI bus.")
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
class DALIDimmableLamp(DALIGear, BaseDimmer):
|
|
490
|
+
manual_add = False
|
|
491
|
+
name = 'DALI Dimmable Lamp'
|
|
492
|
+
discovery_msg = _("Please hook up your new DALI lamp to your DALI bus.")
|
|
420
493
|
|
simo/fleet/forms.py
CHANGED
|
@@ -12,7 +12,8 @@ from simo.core.widgets import LogOutputWidget
|
|
|
12
12
|
from simo.core.utils.easing import EASING_CHOICES
|
|
13
13
|
from simo.core.utils.validators import validate_slaves
|
|
14
14
|
from simo.core.utils.admin import AdminFormActionForm
|
|
15
|
-
from .models import Colonel, ColonelPin,
|
|
15
|
+
from .models import Colonel, ColonelPin, Interface
|
|
16
|
+
from .utils import INTERFACES_PINS_MAP
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class ColonelPinChoiceField(forms.ModelChoiceField):
|
|
@@ -23,6 +24,11 @@ class ColonelPinChoiceField(forms.ModelChoiceField):
|
|
|
23
24
|
filter_by = 'colonel'
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
class ColonelInterfacesChoiceField(forms.ModelChoiceField):
|
|
28
|
+
filter_by = 'colonel'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
26
32
|
class ColonelAdminForm(forms.ModelForm):
|
|
27
33
|
log = forms.CharField(
|
|
28
34
|
widget=forms.HiddenInput, required=False
|
|
@@ -52,34 +58,29 @@ class MoveColonelForm(AdminFormActionForm):
|
|
|
52
58
|
)
|
|
53
59
|
|
|
54
60
|
|
|
55
|
-
class
|
|
56
|
-
scl_pin = ColonelPinChoiceField(
|
|
57
|
-
queryset=ColonelPin.objects.filter(output=True, native=True),
|
|
58
|
-
widget=autocomplete.ListSelect2(
|
|
59
|
-
url='autocomplete-colonel-pins',
|
|
60
|
-
forward=[
|
|
61
|
-
forward.Self(),
|
|
62
|
-
forward.Field('colonel'),
|
|
63
|
-
forward.Const({'output': True, 'native': True}, 'filters')
|
|
64
|
-
]
|
|
65
|
-
)
|
|
66
|
-
)
|
|
67
|
-
sda_pin = ColonelPinChoiceField(
|
|
68
|
-
queryset=ColonelPin.objects.filter(output=True, native=True),
|
|
69
|
-
widget=autocomplete.ListSelect2(
|
|
70
|
-
url='autocomplete-colonel-pins',
|
|
71
|
-
forward=[
|
|
72
|
-
forward.Self(),
|
|
73
|
-
forward.Field('colonel'),
|
|
74
|
-
forward.Const({'output': True, 'native': True}, 'filters')
|
|
75
|
-
]
|
|
76
|
-
)
|
|
77
|
-
)
|
|
61
|
+
class InterfaceAdminForm(forms.ModelForm):
|
|
78
62
|
|
|
79
63
|
class Meta:
|
|
80
|
-
model =
|
|
64
|
+
model = Interface
|
|
81
65
|
fields = '__all__'
|
|
82
66
|
|
|
67
|
+
|
|
68
|
+
def clean(self):
|
|
69
|
+
if self.instance.pk:
|
|
70
|
+
return self.cleaned_data
|
|
71
|
+
|
|
72
|
+
for pin_no in INTERFACES_PINS_MAP[self.cleaned_data['no']]:
|
|
73
|
+
cpin = ColonelPin.objects.get(
|
|
74
|
+
colonel=self.instance.colonel, no=pin_no
|
|
75
|
+
)
|
|
76
|
+
if cpin.occupied_by:
|
|
77
|
+
raise forms.ValidationError(
|
|
78
|
+
f"Interface can not be created, because "
|
|
79
|
+
f"GPIO{cpin} is already occupied by {cpin.occupied_by}."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
83
84
|
def clean_scl_pin(self):
|
|
84
85
|
if self.cleaned_data['scl_pin'].occupied_by \
|
|
85
86
|
and self.cleaned_data['scl_pin'].occupied_by != self.instance:
|
|
@@ -416,13 +417,16 @@ class ColonelDHTSensorConfigForm(ColonelComponentForm):
|
|
|
416
417
|
|
|
417
418
|
|
|
418
419
|
class BME680SensorConfigForm(ColonelComponentForm):
|
|
419
|
-
|
|
420
|
-
|
|
420
|
+
interface = ColonelInterfacesChoiceField(
|
|
421
|
+
queryset=Interface.objects.filter(type='i2c'),
|
|
421
422
|
widget=autocomplete.ListSelect2(
|
|
422
|
-
url='autocomplete-
|
|
423
|
+
url='autocomplete-interfaces',
|
|
423
424
|
forward=[
|
|
424
425
|
forward.Self(),
|
|
425
426
|
forward.Field('colonel'),
|
|
427
|
+
forward.Const(
|
|
428
|
+
{'type': 'i2c'}, 'filters'
|
|
429
|
+
)
|
|
426
430
|
]
|
|
427
431
|
)
|
|
428
432
|
)
|
|
@@ -437,15 +441,22 @@ class BME680SensorConfigForm(ColonelComponentForm):
|
|
|
437
441
|
|
|
438
442
|
)
|
|
439
443
|
|
|
444
|
+
def save(self, commit=True):
|
|
445
|
+
self.instance.config['i2c_interface'] = self.cleaned_data['interface'].no
|
|
446
|
+
return super().save(commit=commit)
|
|
447
|
+
|
|
440
448
|
|
|
441
449
|
class MPC9808SensorConfigForm(ColonelComponentForm):
|
|
442
|
-
|
|
443
|
-
|
|
450
|
+
interface = ColonelInterfacesChoiceField(
|
|
451
|
+
queryset=Interface.objects.filter(type='i2c'),
|
|
444
452
|
widget=autocomplete.ListSelect2(
|
|
445
|
-
url='autocomplete-
|
|
453
|
+
url='autocomplete-interfaces',
|
|
446
454
|
forward=[
|
|
447
455
|
forward.Self(),
|
|
448
456
|
forward.Field('colonel'),
|
|
457
|
+
forward.Const(
|
|
458
|
+
{'type': 'i2c'}, 'filters'
|
|
459
|
+
)
|
|
449
460
|
]
|
|
450
461
|
)
|
|
451
462
|
)
|
|
@@ -460,6 +471,10 @@ class MPC9808SensorConfigForm(ColonelComponentForm):
|
|
|
460
471
|
|
|
461
472
|
)
|
|
462
473
|
|
|
474
|
+
def save(self, commit=True):
|
|
475
|
+
self.instance.config['i2c_interface'] = self.cleaned_data['interface'].no
|
|
476
|
+
return super().save(commit=commit)
|
|
477
|
+
|
|
463
478
|
|
|
464
479
|
class ColonelTouchSensorConfigForm(ColonelComponentForm):
|
|
465
480
|
pin = ColonelPinChoiceField(
|
|
@@ -987,7 +1002,6 @@ class BurglarSmokeDetectorConfigForm(ColonelComponentForm):
|
|
|
987
1002
|
|
|
988
1003
|
|
|
989
1004
|
class TTLockConfigForm(ColonelComponentForm):
|
|
990
|
-
pass
|
|
991
1005
|
|
|
992
1006
|
def clean(self):
|
|
993
1007
|
if not self.instance or not self.instance.pk:
|
|
@@ -1002,7 +1016,6 @@ class TTLockConfigForm(ColonelComponentForm):
|
|
|
1002
1016
|
)
|
|
1003
1017
|
return self.cleaned_data
|
|
1004
1018
|
|
|
1005
|
-
|
|
1006
1019
|
def save(self, commit=True):
|
|
1007
1020
|
obj = super(ColonelComponentForm, self).save(commit)
|
|
1008
1021
|
if commit:
|
|
@@ -1010,3 +1023,25 @@ class TTLockConfigForm(ColonelComponentForm):
|
|
|
1010
1023
|
self.cleaned_data['colonel'].save()
|
|
1011
1024
|
return obj
|
|
1012
1025
|
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
class DALIDeviceConfigForm(ColonelComponentForm):
|
|
1029
|
+
interface = ColonelInterfacesChoiceField(
|
|
1030
|
+
queryset=Interface.objects.filter(type='dali'),
|
|
1031
|
+
widget=autocomplete.ListSelect2(
|
|
1032
|
+
url='autocomplete-interfaces',
|
|
1033
|
+
forward=[
|
|
1034
|
+
forward.Self(),
|
|
1035
|
+
forward.Field('colonel'),
|
|
1036
|
+
forward.Const(
|
|
1037
|
+
{'type': 'dali'}, 'filters'
|
|
1038
|
+
)
|
|
1039
|
+
]
|
|
1040
|
+
)
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
def save(self, commit=True):
|
|
1044
|
+
self.instance.config['dali_interface'] = self.cleaned_data['interface'].no
|
|
1045
|
+
return super().save(commit=commit)
|
|
1046
|
+
|
|
1047
|
+
|
simo/fleet/gateways.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import datetime
|
|
2
|
+
import time
|
|
2
3
|
from django.utils import timezone
|
|
3
4
|
from simo.core.gateways import BaseObjectCommandsGatewayHandler
|
|
4
5
|
from simo.core.forms import BaseGatewayForm
|
|
@@ -14,7 +15,7 @@ class FleetGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
14
15
|
periodic_tasks = (
|
|
15
16
|
('look_for_updates', 600),
|
|
16
17
|
('watch_colonels_connection', 30),
|
|
17
|
-
('push_discoveries',
|
|
18
|
+
('push_discoveries', 10),
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
def _on_mqtt_message(self, client, userdata, msg):
|
|
@@ -37,9 +38,12 @@ class FleetGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
37
38
|
def push_discoveries(self):
|
|
38
39
|
from .models import Colonel
|
|
39
40
|
for gw in Gateway.objects.filter(
|
|
40
|
-
type=self.uid,
|
|
41
|
-
discovery__has_key='start',
|
|
41
|
+
type=self.uid, discovery__has_key='start',
|
|
42
42
|
).exclude(discovery__has_key='finished'):
|
|
43
|
+
if time.time() - gw.discovery.get('last_check') > 10:
|
|
44
|
+
gw.finish_discovery()
|
|
45
|
+
continue
|
|
46
|
+
|
|
43
47
|
colonel = Colonel.objects.get(
|
|
44
48
|
id=gw.discovery['init_data']['colonel']['val'][0]['pk']
|
|
45
49
|
)
|
simo/fleet/managers.py
CHANGED
|
@@ -22,11 +22,13 @@ class ColonelPinsManager(models.Manager):
|
|
|
22
22
|
return qs
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class InterfacesManager(models.Manager):
|
|
26
26
|
|
|
27
27
|
def get_queryset(self):
|
|
28
28
|
qs = super().get_queryset()
|
|
29
29
|
instance = get_current_instance()
|
|
30
30
|
if instance:
|
|
31
31
|
qs = qs.filter(colonel__instance=instance)
|
|
32
|
-
return qs
|
|
32
|
+
return qs
|
|
33
|
+
|
|
34
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 3.2.9 on 2024-04-15 07:36
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('fleet', '0031_alter_colonel_type'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name='colonel',
|
|
16
|
+
name='logs_stream',
|
|
17
|
+
field=models.BooleanField(default=False, help_text='ATENTION! Causes serious overhead and significantly degrades the lifespan of a chip due to a lot of writes to the memory. It also causes Colonel websocket to run out of memory and reset if a lot of data is being transmitted. Leave this off, unleess you know what you are doing!'),
|
|
18
|
+
),
|
|
19
|
+
migrations.CreateModel(
|
|
20
|
+
name='Interface',
|
|
21
|
+
fields=[
|
|
22
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
23
|
+
('no', models.PositiveIntegerField(choices=[(1, '1'), (2, '2')])),
|
|
24
|
+
('type', models.CharField(choices=[('i2c', 'I2C'), ('dali', 'DALI')], max_length=20)),
|
|
25
|
+
('pin_a', models.ForeignKey(editable=False, limit_choices_to={'native': True, 'output': True}, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interface_a', to='fleet.colonelpin')),
|
|
26
|
+
('pin_b', models.ForeignKey(editable=False, limit_choices_to={'native': True, 'output': True}, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interface_b', to='fleet.colonelpin')),
|
|
27
|
+
('colonel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='fleet.colonel')),
|
|
28
|
+
],
|
|
29
|
+
options={
|
|
30
|
+
'unique_together': {('colonel', 'no')},
|
|
31
|
+
},
|
|
32
|
+
),
|
|
33
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by Django 3.2.9 on 2024-04-15 07:36
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
def create_objects(apps, schema_editor):
|
|
6
|
+
I2CInterface = apps.get_model("fleet", "I2CInterface")
|
|
7
|
+
Interface = apps.get_model("fleet", "Interface")
|
|
8
|
+
for i2c_i in I2CInterface.objects.filter(no__gt=0):
|
|
9
|
+
Interface.objects.create(
|
|
10
|
+
colonel=i2c_i.colonel, type='i2c',
|
|
11
|
+
pin_a=i2c_i.scl_pin, pin_b=i2c_i.sda_pin
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def delete_objects(apps, schema_editor):
|
|
16
|
+
Interface = apps.get_model("fleet", "Interface")
|
|
17
|
+
Interface.delete()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Migration(migrations.Migration):
|
|
21
|
+
|
|
22
|
+
dependencies = [
|
|
23
|
+
('fleet', '0032_auto_20240415_0736'),
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
operations = [
|
|
27
|
+
migrations.RunPython(create_objects, delete_objects),
|
|
28
|
+
]
|
|
Binary file
|
|
Binary file
|
simo/fleet/models.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
import time
|
|
3
|
+
from django.core.exceptions import ValidationError
|
|
3
4
|
from django.db import transaction
|
|
4
5
|
from django.db import models
|
|
5
6
|
from django.db.models.signals import post_save, pre_delete, post_delete
|
|
@@ -11,8 +12,8 @@ from simo.core.models import Instance, Gateway, Component
|
|
|
11
12
|
from simo.core.utils.helpers import get_random_string
|
|
12
13
|
from simo.core.events import GatewayObjectCommand
|
|
13
14
|
from .gateways import FleetGatewayHandler
|
|
14
|
-
from .managers import ColonelsManager, ColonelPinsManager,
|
|
15
|
-
from .utils import GPIO_PINS
|
|
15
|
+
from .managers import ColonelsManager, ColonelPinsManager, InterfacesManager
|
|
16
|
+
from .utils import GPIO_PINS, INTERFACES_PINS_MAP
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
|
|
@@ -181,10 +182,12 @@ class Colonel(DirtyFieldsMixin, models.Model):
|
|
|
181
182
|
pin.save()
|
|
182
183
|
|
|
183
184
|
for interface in self.i2c_interfaces.all():
|
|
184
|
-
interface.sda_pin
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
interface.scl_pin
|
|
185
|
+
if interface.sda_pin:
|
|
186
|
+
interface.sda_pin.occupied_by = interface
|
|
187
|
+
interface.sda_pin.save()
|
|
188
|
+
if interface.scl_pin:
|
|
189
|
+
interface.scl_pin.occupied_by = interface
|
|
190
|
+
interface.scl_pin.save()
|
|
188
191
|
|
|
189
192
|
|
|
190
193
|
def move_to(self, other_colonel):
|
|
@@ -256,12 +259,6 @@ def after_colonel_save(sender, instance, created, *args, **kwargs):
|
|
|
256
259
|
capacitive=data.get('capacitive'), adc=data.get('adc'),
|
|
257
260
|
native=data.get('native'), note=data.get('note')
|
|
258
261
|
)
|
|
259
|
-
if instance.type in ('ample-wall', 'game-changer'):
|
|
260
|
-
I2CInterface.objects.create(
|
|
261
|
-
colonel=instance, name='Main', no=0,
|
|
262
|
-
scl_pin=ColonelPin.objects.get(colonel=instance, no=4),
|
|
263
|
-
sda_pin=ColonelPin.objects.get(colonel=instance, no=15),
|
|
264
|
-
)
|
|
265
262
|
|
|
266
263
|
|
|
267
264
|
@receiver(pre_delete, sender=Component)
|
|
@@ -310,7 +307,7 @@ class I2CInterface(models.Model):
|
|
|
310
307
|
default=100000, help_text="100000 - is a good middle point!"
|
|
311
308
|
)
|
|
312
309
|
|
|
313
|
-
objects =
|
|
310
|
+
objects = InterfacesManager()
|
|
314
311
|
|
|
315
312
|
class Meta:
|
|
316
313
|
unique_together = 'colonel', 'no'
|
|
@@ -319,7 +316,7 @@ class I2CInterface(models.Model):
|
|
|
319
316
|
return self.name
|
|
320
317
|
|
|
321
318
|
|
|
322
|
-
@receiver(
|
|
319
|
+
@receiver(post_delete, sender=I2CInterface)
|
|
323
320
|
def post_i2c_interface_delete(sender, instance, *args, **kwargs):
|
|
324
321
|
with transaction.atomic():
|
|
325
322
|
ct = ContentType.objects.get_for_model(instance)
|
|
@@ -334,3 +331,74 @@ def post_i2c_interface_delete(sender, instance, *args, **kwargs):
|
|
|
334
331
|
instance.scl_pin.save()
|
|
335
332
|
instance.sda_pin.occupied_by = instance
|
|
336
333
|
instance.sda_pin.save()
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class Interface(models.Model):
|
|
337
|
+
colonel = models.ForeignKey(
|
|
338
|
+
Colonel, on_delete=models.CASCADE, related_name='interfaces'
|
|
339
|
+
)
|
|
340
|
+
no = models.PositiveIntegerField(choices=((1, "1"), (2, "2")))
|
|
341
|
+
type = models.CharField(
|
|
342
|
+
max_length=20, choices=(('i2c', "I2C"), ('dali', "DALI"))
|
|
343
|
+
)
|
|
344
|
+
pin_a = models.ForeignKey(
|
|
345
|
+
ColonelPin, on_delete=models.CASCADE, limit_choices_to={
|
|
346
|
+
'native': True, 'output': True,
|
|
347
|
+
}, verbose_name="Pin A (scl)", null=True, related_name='interface_a',
|
|
348
|
+
editable=False
|
|
349
|
+
)
|
|
350
|
+
pin_b = models.ForeignKey(
|
|
351
|
+
ColonelPin, on_delete=models.CASCADE, limit_choices_to={
|
|
352
|
+
'native': True, 'output': True,
|
|
353
|
+
}, verbose_name="Pin B (sda)", null=True, related_name='interface_b',
|
|
354
|
+
editable=False
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
objects = InterfacesManager()
|
|
358
|
+
|
|
359
|
+
class Meta:
|
|
360
|
+
unique_together = 'colonel', 'no'
|
|
361
|
+
|
|
362
|
+
def __str__(self):
|
|
363
|
+
return f"{self.no} - {self.get_type_display()}"
|
|
364
|
+
|
|
365
|
+
def save(self, *args, **kwargs):
|
|
366
|
+
if not self.pk:
|
|
367
|
+
for pin_no in INTERFACES_PINS_MAP[self.no]:
|
|
368
|
+
cpin = ColonelPin.objects.get(colonel=self.colonel, no=pin_no)
|
|
369
|
+
if cpin.occupied_by:
|
|
370
|
+
raise ValidationError(
|
|
371
|
+
f"Interface can not be created, because "
|
|
372
|
+
f"GPIO{cpin} is already occupied by {cpin.occupied_by}."
|
|
373
|
+
)
|
|
374
|
+
return super().save(*args, **kwargs)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
@receiver(post_save, sender=Interface)
|
|
378
|
+
def post_interface_save(sender, instance, created, *args, **kwargs):
|
|
379
|
+
if created:
|
|
380
|
+
instance.pin_a = ColonelPin.objects.get(
|
|
381
|
+
colonel=instance.colonel, no=INTERFACES_PINS_MAP[instance.no][0]
|
|
382
|
+
)
|
|
383
|
+
instance.pin_a.occupied_by = instance
|
|
384
|
+
instance.pin_a.save()
|
|
385
|
+
instance.pin_b = ColonelPin.objects.get(
|
|
386
|
+
colonel=instance.colonel, no=INTERFACES_PINS_MAP[instance.no][1]
|
|
387
|
+
)
|
|
388
|
+
instance.pin_b.occupied_by = instance
|
|
389
|
+
instance.pin_b.save()
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
@receiver(post_delete, sender=Interface)
|
|
393
|
+
def post_interface_delete(sender, instance, *args, **kwargs):
|
|
394
|
+
with transaction.atomic():
|
|
395
|
+
ct = ContentType.objects.get_for_model(instance)
|
|
396
|
+
for pin in ColonelPin.objects.filter(
|
|
397
|
+
occupied_by_content_type=ct,
|
|
398
|
+
occupied_by_id=instance.id
|
|
399
|
+
):
|
|
400
|
+
pin.occupied_by_content_type = None
|
|
401
|
+
pin.occupied_by_content_id = None
|
|
402
|
+
pin.save()
|
|
403
|
+
|
|
404
|
+
|
simo/fleet/socket_consumers.py
CHANGED
|
@@ -218,15 +218,14 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
config_data['settings'].update(instance_options)
|
|
221
|
-
|
|
222
|
-
self.colonel.
|
|
223
|
-
'
|
|
221
|
+
interfaces = await sync_to_async(list, thread_sensitive=True)(
|
|
222
|
+
self.colonel.interfaces.all().select_related(
|
|
223
|
+
'pin_a', 'pin_b'
|
|
224
224
|
)
|
|
225
225
|
)
|
|
226
|
-
for
|
|
227
|
-
config_data['interfaces']['
|
|
228
|
-
'
|
|
229
|
-
'freq': i2c_interface.freq
|
|
226
|
+
for interface in interfaces:
|
|
227
|
+
config_data['interfaces'][f'{interface.type}-{interface.no}'] = {
|
|
228
|
+
'pin_a': interface.pin_a.no, 'pin_b': interface.pin_b.no,
|
|
230
229
|
}
|
|
231
230
|
components = await sync_to_async(
|
|
232
231
|
list, thread_sensitive=True
|
|
@@ -319,6 +318,11 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
319
318
|
asyncio.run(self.send_data({
|
|
320
319
|
'command': 'discover-ttlock'
|
|
321
320
|
}))
|
|
321
|
+
elif payload.get('command') == 'discover-dali':
|
|
322
|
+
print("SEND discover-dali command!")
|
|
323
|
+
asyncio.run(self.send_data({
|
|
324
|
+
'command': 'discover-dali', 'i': payload['interface']
|
|
325
|
+
}))
|
|
322
326
|
elif payload.get('command') == 'finalize':
|
|
323
327
|
asyncio.run(self.send_data({
|
|
324
328
|
'command': 'finalize',
|
|
@@ -420,18 +424,21 @@ class FleetConsumer(AsyncWebsocketConsumer):
|
|
|
420
424
|
except Exception as e:
|
|
421
425
|
print(traceback.format_exc(), file=sys.stderr)
|
|
422
426
|
|
|
423
|
-
elif '
|
|
427
|
+
elif 'discovery-result' in data:
|
|
424
428
|
def process_discovery_result():
|
|
425
|
-
|
|
426
|
-
if
|
|
427
|
-
|
|
429
|
+
# check if component is already created
|
|
430
|
+
if data['discovery-result'] == 'success':
|
|
431
|
+
comp = Component.objects.filter(
|
|
428
432
|
meta__finalization_data__temp_id=data['result']['id']
|
|
429
433
|
).first()
|
|
434
|
+
if comp:
|
|
435
|
+
return comp
|
|
436
|
+
|
|
437
|
+
self.gateway.refresh_from_db()
|
|
430
438
|
try:
|
|
431
439
|
self.gateway.process_discovery(data)
|
|
432
440
|
except Exception as e:
|
|
433
441
|
print(traceback.format_exc(), file=sys.stderr)
|
|
434
|
-
self.gateway.finish_discovery()
|
|
435
442
|
|
|
436
443
|
finished_comp = await sync_to_async(
|
|
437
444
|
process_discovery_result, thread_sensitive=True
|
simo/fleet/utils.py
CHANGED
|
@@ -58,7 +58,7 @@ for no, data in BASE_ESP32_GPIO_PINS.items():
|
|
|
58
58
|
|
|
59
59
|
# ample-wall
|
|
60
60
|
for no, data in BASE_ESP32_GPIO_PINS.items():
|
|
61
|
-
if no in (
|
|
61
|
+
if no in (12, 13, 14, 23, 32, 33, 34, 36, 39):
|
|
62
62
|
GPIO_PINS['ample-wall'][no] = GPIO_PIN_DEFAULTS.copy()
|
|
63
63
|
GPIO_PINS['ample-wall'][no].update(data)
|
|
64
64
|
|
|
@@ -114,3 +114,8 @@ for no, data in BASE_ESP32_GPIO_PINS.items():
|
|
|
114
114
|
GPIO_PINS['4-relays'][no]['note'] = 'Relay4'
|
|
115
115
|
else:
|
|
116
116
|
GPIO_PINS['4-relays'][no].update(data)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
INTERFACES_PINS_MAP = {
|
|
120
|
+
1: [13, 23], 2: [32, 33]
|
|
121
|
+
}
|
simo/fleet/views.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
from django.contrib.contenttypes.models import ContentType
|
|
2
1
|
from django.http import HttpResponse, Http404
|
|
3
2
|
from django.db.models import Q
|
|
4
3
|
from dal import autocomplete
|
|
5
4
|
from simo.core.utils.helpers import search_queryset
|
|
6
|
-
from .models import Colonel, ColonelPin,
|
|
5
|
+
from .models import Colonel, ColonelPin, Interface
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
def colonels_ping(request):
|
|
@@ -43,20 +42,22 @@ class PinsSelectAutocomplete(autocomplete.Select2QuerySetView):
|
|
|
43
42
|
return qs
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
class
|
|
45
|
+
class InterfaceSelectAutocomplete(autocomplete.Select2ListView):
|
|
47
46
|
|
|
48
47
|
def get_list(self):
|
|
49
48
|
if not self.request.user.is_staff:
|
|
50
|
-
return
|
|
49
|
+
return Interface.objects.none()
|
|
51
50
|
|
|
52
51
|
try:
|
|
53
52
|
colonel = Colonel.objects.get(
|
|
54
53
|
pk=self.forwarded.get("colonel")
|
|
55
54
|
)
|
|
56
55
|
except:
|
|
57
|
-
return
|
|
56
|
+
return Interface.objects.none()
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
qs = Interface.objects.filter(colonel=colonel)
|
|
59
|
+
|
|
60
|
+
if self.forwarded.get('filters'):
|
|
61
|
+
qs = qs.filter(**self.forwarded.get('filters'))
|
|
62
|
+
|
|
63
|
+
return qs
|
|
@@ -25,8 +25,8 @@ simo/_hub_template/hub/settings.py,sha256=4QhvhbtLRxHvAntwqG_qeAAtpDUqKvN4jzw9u3
|
|
|
25
25
|
simo/_hub_template/hub/supervisor.conf,sha256=IY3fdK0fDD2eAothB0n54xhjQj8LYoXIR96-Adda5Z8,1353
|
|
26
26
|
simo/_hub_template/hub/urls.py,sha256=Ydm-1BkYAzWeEF-MKSDIFf-7aE4qNLPm48-SA51XgJQ,25
|
|
27
27
|
simo/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
simo/core/admin.py,sha256=
|
|
29
|
-
simo/core/api.py,sha256=
|
|
28
|
+
simo/core/admin.py,sha256=MoYz7B5YaTkF2JeacaqsR177N2IagKXc-rG0FTXjJ1w,17622
|
|
29
|
+
simo/core/api.py,sha256=OVvv3a7KYJGbuUgSOfWzPg8hoCCRhdDejQ2kVs0H2p8,23803
|
|
30
30
|
simo/core/api_auth.py,sha256=_3hG4e1eLKrcRnSAOB_xTL6cwtOJ2_7JS7GZU_iqTgA,1251
|
|
31
31
|
simo/core/api_meta.py,sha256=li4KLFl6xTYOoD8pgS8PYcjqTZlzhXI0reAkt06PZFA,3404
|
|
32
32
|
simo/core/app_widgets.py,sha256=EEQOto3fGR0syDqpJE38tQrx8DoTTyg26nF5kYzHY38,2018
|
|
@@ -34,19 +34,19 @@ 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=2D7YCLktx7a-4tn80DenQP2CdY0dc2bWg6IRU69YTZ8,27246
|
|
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
|
|
41
|
-
simo/core/forms.py,sha256=
|
|
41
|
+
simo/core/forms.py,sha256=OQTPuacid9AoEvZ86G9p6ILuviqJCtSDuwk2WlLj43E,21484
|
|
42
42
|
simo/core/gateways.py,sha256=s_c2W0v2_te89i6LS4Nj7F2wn9UwjZXPT7pfy6SToVo,3714
|
|
43
43
|
simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
|
|
44
44
|
simo/core/managers.py,sha256=WoQ4OX3akIvoroSYji-nLVqXBSJzCiC1u_IiWkKbKmA,2413
|
|
45
45
|
simo/core/middleware.py,sha256=64PYjnyRnYf4sgMvPfR0oQqf9UEtxUwnhJe3RV6z_HI,2040
|
|
46
|
-
simo/core/models.py,sha256=
|
|
46
|
+
simo/core/models.py,sha256=VNoHjHUFQRvKH4ejv4kGv5E6a4bSOhuM8sfAlRYaj-g,19036
|
|
47
47
|
simo/core/permissions.py,sha256=UmFjGPDWtAUbaWxJsWORb2q6BREHqndv9mkSIpnmdLk,1379
|
|
48
48
|
simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
|
|
49
|
-
simo/core/serializers.py,sha256=
|
|
49
|
+
simo/core/serializers.py,sha256=miEh2Sd47KmB0viyNlwrEG_1kxYiTUrvQQvisEoLYuA,15759
|
|
50
50
|
simo/core/signal_receivers.py,sha256=EZ8NSYZxUgSaLS16YZdK7T__l8dl0joMRllOxx5PUt4,2809
|
|
51
51
|
simo/core/socket_consumers.py,sha256=n7VE2Fvqt4iEAYLTRbTPOcI-7tszMAADu7gimBxB-Fg,9635
|
|
52
52
|
simo/core/storage.py,sha256=YlxmdRs-zhShWtFKgpJ0qp2NDBuIkJGYC1OJzqkbttQ,572
|
|
@@ -56,8 +56,8 @@ simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
|
|
|
56
56
|
simo/core/views.py,sha256=hlAKpAbCbqI3a-uL5tDp532T2oLFiF0MBzKUJ_SNzo0,5833
|
|
57
57
|
simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
|
|
58
58
|
simo/core/__pycache__/__init__.cpython-38.pyc,sha256=y0IW37wBUIGa3Eh_ZG28pRqHKoLiPyTgUX2OnbkEPlc,158
|
|
59
|
-
simo/core/__pycache__/admin.cpython-38.pyc,sha256=
|
|
60
|
-
simo/core/__pycache__/api.cpython-38.pyc,sha256=
|
|
59
|
+
simo/core/__pycache__/admin.cpython-38.pyc,sha256=GP3lRW8djW3w_k5jgzs_fuW7j8wnmeysZcDtm5RFnD0,13442
|
|
60
|
+
simo/core/__pycache__/api.cpython-38.pyc,sha256=W-CdACWTu_ebqH52riswadzT7z2mNRZJU8HngqbYXzw,18874
|
|
61
61
|
simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=5UTBr3rDMERAfc0OuOVDwGeQkt6Q7GLBtZJAMBse1sg,1712
|
|
62
62
|
simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=bdk1PG7FuRfFwcvQtF103H0kQrx6Vt0JRiepktWEPh8,2730
|
|
63
63
|
simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=9Es2wZNduzUJv-jZ_HX0-L3vqwpXWBbseEwoC5K6b-w,3465
|
|
@@ -65,19 +65,19 @@ simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=SVl4fF0-yiq7e9gt08jIM6_rL4
|
|
|
65
65
|
simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=hJ6JILI1LqrAtpQMvxnLvljGdW1v1gpvBsD79vFkZ58,3972
|
|
66
66
|
simo/core/__pycache__/base_types.cpython-38.pyc,sha256=Ukc5U63YJbyUcn0cwNMS8nteRSvEJmCszZUfHClKBtg,735
|
|
67
67
|
simo/core/__pycache__/context.cpython-38.pyc,sha256=MSZPDhqMhCpUuBJl3HCIBHZA3BntYeP8RAnQcdqAH9k,1278
|
|
68
|
-
simo/core/__pycache__/controllers.cpython-38.pyc,sha256
|
|
68
|
+
simo/core/__pycache__/controllers.cpython-38.pyc,sha256=-NjuX7iGheE_ZMqkZ6g4ZnnVjdUnFCTlH0awAJxZt2Y,24110
|
|
69
69
|
simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=ELu06Hub4DOidja71ybvD3ZM4HdXiyZjNJrZfnXZXNA,2476
|
|
70
70
|
simo/core/__pycache__/events.cpython-38.pyc,sha256=A1Axx-qftd1r7st7wkO3DkvTdt9-RkcJe5KJhpzJVk8,5109
|
|
71
71
|
simo/core/__pycache__/filters.cpython-38.pyc,sha256=VIMADCBiYhziIyRmxAyUDJluZvuZmiC4bNYWTRsGSao,721
|
|
72
|
-
simo/core/__pycache__/forms.cpython-38.pyc,sha256=
|
|
72
|
+
simo/core/__pycache__/forms.cpython-38.pyc,sha256=KH1SBm1NaDv99yHONenWWJcd4XSIqQ5tqaF8LSoeDws,17843
|
|
73
73
|
simo/core/__pycache__/gateways.cpython-38.pyc,sha256=XBiwMfBkjoQ2re6jvADJOwK0_0Aav-crzie9qtfqT9U,4599
|
|
74
74
|
simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
|
|
75
75
|
simo/core/__pycache__/managers.cpython-38.pyc,sha256=5vstOMfm997CZBBkaSiaS7EojhLTWZlbeA_EQ8u-yfg,2554
|
|
76
76
|
simo/core/__pycache__/middleware.cpython-38.pyc,sha256=bGOFJNEhJeLbpsZp8LYn1VA3paLF5HULHQ6IFKa7Juc,2022
|
|
77
|
-
simo/core/__pycache__/models.cpython-38.pyc,sha256=
|
|
77
|
+
simo/core/__pycache__/models.cpython-38.pyc,sha256=Hl9MXjnnmDTp826aEc5KLqPFl4ZzrT7HTVxVSz2-Vik,16695
|
|
78
78
|
simo/core/__pycache__/permissions.cpython-38.pyc,sha256=uygjPbfRQiEzyo5-McCxsuMDJLbDYO_TLu55U7bJbR0,1809
|
|
79
79
|
simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
|
|
80
|
-
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=
|
|
80
|
+
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=tJf8jV9pPJXnJjUPXCc103wQxC5ZrZaC9SlIR41JomQ,15707
|
|
81
81
|
simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=sgjH_wv-1U99auH5uHb3or0qettPeHAlsz8P7B03ajY,2430
|
|
82
82
|
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=NJUr7nRyHFvmAumxxWpsod5wzVVZM99rCEuJs1utHA4,8432
|
|
83
83
|
simo/core/__pycache__/storage.cpython-38.pyc,sha256=BTkYH8QQyjqI0WOtJC8fHNtgu0YA1vjqZclXjC2vCVI,1116
|
|
@@ -170,6 +170,7 @@ simo/core/migrations/0026_category_instance.py,sha256=Slrev0VvCkqEQhKly2ZcM7QUam
|
|
|
170
170
|
simo/core/migrations/0027_remove_component_tags.py,sha256=V0o_lgKiVU3HfG5V8MTO-j4UVPakGV5lxV0Jo6qAPpQ,325
|
|
171
171
|
simo/core/migrations/0028_rename_subcomponents_component_slaves.py,sha256=ioQcfO2_IIfPc_BZzETmSodsYstzygR9U0ULnhET6ac,373
|
|
172
172
|
simo/core/migrations/0029_auto_20240229_1331.py,sha256=BYXPNwjXApAx7mxE5li3QssfksWTsSjDf_VPQ8iGV8c,1140
|
|
173
|
+
simo/core/migrations/0030_alter_instance_timezone.py,sha256=XZuYr2eD9MvE21Jxfdat8RC3sbc7PaGUfNPaqqxBNzE,23248
|
|
173
174
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
174
175
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=w6GiBXVxWj30Bg4Sn_pFVeA041d-pCrkaq8mR3KuF70,5381
|
|
175
176
|
simo/core/migrations/__pycache__/0002_load_icons.cpython-38.pyc,sha256=Nb9RrPjVYo_RpZ5PmzoaEIWGCeVt4kicpmGiKlBrpIw,2123
|
|
@@ -200,6 +201,7 @@ simo/core/migrations/__pycache__/0026_category_instance.cpython-38.pyc,sha256=0C
|
|
|
200
201
|
simo/core/migrations/__pycache__/0027_remove_component_tags.cpython-38.pyc,sha256=Jadlk2tN_3UfPj-xpZssFs5dftZaPl8reWpPWYQu2nY,538
|
|
201
202
|
simo/core/migrations/__pycache__/0028_rename_subcomponents_component_slaves.cpython-38.pyc,sha256=PSiMp1yDzZ36Ei36U2tcIlvyzGgB5RuvGImrJ__7Q5s,593
|
|
202
203
|
simo/core/migrations/__pycache__/0029_auto_20240229_1331.cpython-38.pyc,sha256=nO6lBU-1SxMQv67jQs7cGgNnot722UVL9pj3UE14I1k,1086
|
|
204
|
+
simo/core/migrations/__pycache__/0030_alter_instance_timezone.cpython-38.pyc,sha256=paRgdijg5o8QzluT4GjSEQIMk6UAF7XmSwjqknXPE_4,16333
|
|
203
205
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=VZmDQ57BTcebuM0KMhjiTOabgWZCBxQmSJzWZos9SO8,169
|
|
204
206
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
205
207
|
simo/core/static/admin/Img/plus.svg,sha256=2NpSFPWqGIjpAQGFI7LDQHPKagEhYkJiJX95ufCoZaI,741
|
|
@@ -10140,7 +10142,7 @@ simo/core/utils/logs.py,sha256=Zn9JQxqCH9Odx2J1BWT84nFCfkJ4Z4p5X8psdll7hNc,2366
|
|
|
10140
10142
|
simo/core/utils/mixins.py,sha256=X6kUPKAi_F-uw7tgm8LEaYalBXpvDA-yrLNFCGr2rks,259
|
|
10141
10143
|
simo/core/utils/model_helpers.py,sha256=3IzJeOvBoYdUJVXCJkY20npOZXPjNPAiEFvuT0OPhwA,884
|
|
10142
10144
|
simo/core/utils/relay.py,sha256=i1xy_nPTgY5Xn0l2W4lNI3xeVUpDQTUUfV3M8h2DeBg,457
|
|
10143
|
-
simo/core/utils/serialization.py,sha256=
|
|
10145
|
+
simo/core/utils/serialization.py,sha256=v0HLQ98r3zOlsf6dv6S4WxOEt6BzmFz2eTXa_iuKjSM,2057
|
|
10144
10146
|
simo/core/utils/type_constants.py,sha256=xR2HXZOw9GZhC47iO1Py5B8mpaQMPbzvqX5nHWakhsY,4116
|
|
10145
10147
|
simo/core/utils/validators.py,sha256=FRO6_K5HAO1OaC-LosApZjh-W3EA-IJZ53HnwEJgqiI,1297
|
|
10146
10148
|
simo/core/utils/__pycache__/__init__.cpython-38.pyc,sha256=NJHPMizDKYRDEyMdQIh-ZRwT-BntwrvYfF450N2RYdI,164
|
|
@@ -10156,39 +10158,39 @@ simo/core/utils/__pycache__/logs.cpython-38.pyc,sha256=BVVeQoOhfRHm3SHnCoE1d5G84
|
|
|
10156
10158
|
simo/core/utils/__pycache__/mixins.cpython-38.pyc,sha256=8Js2T7jVQ7hugRUIRu3rdxW86dJW4KeUUWqKqSkIGb0,615
|
|
10157
10159
|
simo/core/utils/__pycache__/model_helpers.cpython-38.pyc,sha256=QzO0rh1NuQePHDCSLmUCRrAZEnV4o8jh9CF_jp7IoUo,1351
|
|
10158
10160
|
simo/core/utils/__pycache__/relay.cpython-38.pyc,sha256=gs4iN9TWBo_JIW07emIggIcv6gHKuOY_4jfmAFhuL3k,697
|
|
10159
|
-
simo/core/utils/__pycache__/serialization.cpython-38.pyc,sha256=
|
|
10161
|
+
simo/core/utils/__pycache__/serialization.cpython-38.pyc,sha256=9nTbzozDi8Avl6krHvAo67CLdiTrYW0ij3hQtucHty0,1338
|
|
10160
10162
|
simo/core/utils/__pycache__/type_constants.cpython-38.pyc,sha256=bEMvzkBxzc6MKq6gn9A6wszXzMjLTbX-V-IK4NMht8E,3363
|
|
10161
10163
|
simo/core/utils/__pycache__/validators.cpython-38.pyc,sha256=gjeBOjL_keMoRDjdn8v-3F3wcjPIT3Xx5KpTalo0e-Y,1247
|
|
10162
10164
|
simo/fleet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10163
|
-
simo/fleet/admin.py,sha256=
|
|
10165
|
+
simo/fleet/admin.py,sha256=aQulOPtrIQUKj8WvA4GfINfqVA52fcU72yK2hVlcmJ0,5681
|
|
10164
10166
|
simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
|
|
10165
|
-
simo/fleet/auto_urls.py,sha256=
|
|
10167
|
+
simo/fleet/auto_urls.py,sha256=X04oKJWA48wFW5iXg3PPROY2KDdHn_a99orQSE28QC4,518
|
|
10166
10168
|
simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
|
|
10167
|
-
simo/fleet/controllers.py,sha256=
|
|
10168
|
-
simo/fleet/forms.py,sha256=
|
|
10169
|
-
simo/fleet/gateways.py,sha256=
|
|
10170
|
-
simo/fleet/managers.py,sha256=
|
|
10171
|
-
simo/fleet/models.py,sha256=
|
|
10169
|
+
simo/fleet/controllers.py,sha256=VxutXZSZaZHmXGYpqjsC_6DgJsF1ZDZeJwu3px79wSE,16683
|
|
10170
|
+
simo/fleet/forms.py,sha256=pR_KER9u9VtNb5NpSWwI7LrnBBtn9jbEXzUvyFRzoj0,35986
|
|
10171
|
+
simo/fleet/gateways.py,sha256=m-jF8S_kJCI-yLI0UmWm46xZrsHcvSfw2gozZWRoFfE,1707
|
|
10172
|
+
simo/fleet/managers.py,sha256=XOpDOA9L-f_550TNSyXnJbun2EmtGz1TenVTMlUSb8E,807
|
|
10173
|
+
simo/fleet/models.py,sha256=7ZZ1z_cId7z9bEzLHvEEDtpFwUMgIUDesr5hhveDcWg,14136
|
|
10172
10174
|
simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
|
|
10173
10175
|
simo/fleet/serializers.py,sha256=zEpXAXxjk4Rf1JhlNnLTrs20qJggqjvIySbeHVo4Tt4,1505
|
|
10174
|
-
simo/fleet/socket_consumers.py,sha256=
|
|
10175
|
-
simo/fleet/utils.py,sha256=
|
|
10176
|
-
simo/fleet/views.py,sha256=
|
|
10176
|
+
simo/fleet/socket_consumers.py,sha256=ii5L1di8iXzn-l91zVFQ_g9YQm_a-_Z-Dn5OnKbJ9FI,19876
|
|
10177
|
+
simo/fleet/utils.py,sha256=2gcjbwQawsGw2edr_wm9q6XacGpYqO-gd4BF1t0Hg6U,3511
|
|
10178
|
+
simo/fleet/views.py,sha256=WMMG8rEJA6RTOf3U-2sYbiSH2Q3rBC-6kYg9KpYHtlI,1686
|
|
10177
10179
|
simo/fleet/__pycache__/__init__.cpython-38.pyc,sha256=pIZE7EL6-cuJ3pQtaSwjKLrKLsTYelp1k9sRhXKLh6s,159
|
|
10178
|
-
simo/fleet/__pycache__/admin.cpython-38.pyc,sha256=
|
|
10180
|
+
simo/fleet/__pycache__/admin.cpython-38.pyc,sha256=Tw3g9JKzJ3ICjWnHQedU8qV7RSZeJL81jSYpvTLK5bM,5798
|
|
10179
10181
|
simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rL9fb7cCQatyFvXyKmlNOKmxVo8vHYeYhfSiAgchyAs,3110
|
|
10180
|
-
simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=
|
|
10182
|
+
simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=SqyTuaz_kEBvx-bL46SclsZEEP5RFh6U6TGKyXDdiOE,565
|
|
10181
10183
|
simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
|
|
10182
|
-
simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10183
|
-
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=
|
|
10184
|
-
simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=
|
|
10185
|
-
simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=
|
|
10186
|
-
simo/fleet/__pycache__/models.cpython-38.pyc,sha256=
|
|
10184
|
+
simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=sOxMEUCc347vDlsC2Pp9h5jxyhax2dFBAVEgP_aTN3s,14848
|
|
10185
|
+
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=7AjtKMSUAuaxLIRx1lvEfRaAlujKRyIMK7gnJjru-fI,25650
|
|
10186
|
+
simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=Qpfw3NYxCS9tS63FaZz8fdL9fq5X1k5QcQlaJl-szb4,2152
|
|
10187
|
+
simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=8uz-xpUiqbGDgXIZ_XRZtFb-Tju6NGxflGg-Ee4Yo6k,1310
|
|
10188
|
+
simo/fleet/__pycache__/models.cpython-38.pyc,sha256=1nBzbxLzIOYxss3wx0-lyGP-JCHnGdbADH_NDQ4If50,12273
|
|
10187
10189
|
simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
|
|
10188
10190
|
simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=yuY2H7jcboQGZdjb5WIsgNHXFhI9IPMUrEu9NgSiXNo,2452
|
|
10189
|
-
simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=
|
|
10190
|
-
simo/fleet/__pycache__/utils.cpython-38.pyc,sha256=
|
|
10191
|
-
simo/fleet/__pycache__/views.cpython-38.pyc,sha256=
|
|
10191
|
+
simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=5bmMyD3gRyfR2Hbh0KwZwMPYzZR8NPWuMhN8PHWOqLg,14408
|
|
10192
|
+
simo/fleet/__pycache__/utils.cpython-38.pyc,sha256=dTuvW9MnhUycwdCc6eHYfHsMlvZw-CmEWXWYu18X8Uw,1955
|
|
10193
|
+
simo/fleet/__pycache__/views.cpython-38.pyc,sha256=HLHXI3JgCDUWP7oY944nBqpVVu0D6-qOuiSMraNUdq8,1825
|
|
10192
10194
|
simo/fleet/migrations/0001_initial.py,sha256=lce8nkD8Sz6pYr-XJSpDm4CMDuB6TA__WtnHpIp-eA4,1326
|
|
10193
10195
|
simo/fleet/migrations/0002_auto_20220422_0743.py,sha256=sFOfAjnQOzcJjE8lHrrHgTaGilJNYswMdXphgVzUZqY,825
|
|
10194
10196
|
simo/fleet/migrations/0003_auto_20220422_0752.py,sha256=VcH7DyMAniEwT76hDVofS8FTNpM3nxz_J9AC2zKHDSA,543
|
|
@@ -10220,6 +10222,8 @@ simo/fleet/migrations/0028_remove_i2cinterface_scl_pin_no_and_more.py,sha256=Ceo
|
|
|
10220
10222
|
simo/fleet/migrations/0029_alter_i2cinterface_scl_pin_and_more.py,sha256=aquymc1ZcUVgdrqZxl3viN6kiCHtw4HjgL6n4d0cSpQ,886
|
|
10221
10223
|
simo/fleet/migrations/0030_colonelpin_label_alter_colonel_type.py,sha256=5T5bmQxPZrG0UseCLd7ssV-AeFF3O4T_DFxLu3whSqg,706
|
|
10222
10224
|
simo/fleet/migrations/0031_alter_colonel_type.py,sha256=Kv_Gld-X0NZ7d2P9WBXfIlhq4iPH1_NnzDrPyy9_Pos,522
|
|
10225
|
+
simo/fleet/migrations/0032_auto_20240415_0736.py,sha256=yBT48pIfDBm7J1Y3LrvNtmihRbwEXjmBGBB1ghc2z5Y,1800
|
|
10226
|
+
simo/fleet/migrations/0033_auto_20240415_0736.py,sha256=_7p3-Qdc7aaP4mDwny_ig5E4XoEm8t2PoZ3-UeQ4jio,758
|
|
10223
10227
|
simo/fleet/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10224
10228
|
simo/fleet/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=9kc1UyMEYkRNVnZ7iwZbiW1t3qWXROvWrI2G1BdzIaA,1250
|
|
10225
10229
|
simo/fleet/migrations/__pycache__/0002_auto_20220422_0743.cpython-38.pyc,sha256=8oxhGb7rL8QYKlBLU3pOYcd8aHeQWDB9I8awkK04mXg,841
|
|
@@ -10252,6 +10256,8 @@ simo/fleet/migrations/__pycache__/0028_remove_i2cinterface_scl_pin_no_and_more.c
|
|
|
10252
10256
|
simo/fleet/migrations/__pycache__/0029_alter_i2cinterface_scl_pin_and_more.cpython-38.pyc,sha256=S0V5f3Q366v6NlSBW78IqjC8evoFoOTnoYmsFhsOBO4,902
|
|
10253
10257
|
simo/fleet/migrations/__pycache__/0030_colonelpin_label_alter_colonel_type.cpython-38.pyc,sha256=sfglSDxXLKJ0qE8Dl3MYjv5hbszpDtb9CDxatoEzPSw,853
|
|
10254
10258
|
simo/fleet/migrations/__pycache__/0031_alter_colonel_type.cpython-38.pyc,sha256=zXX254ZgEE4uSV8xnLdH9DM3qy-ICmbrT05i0Q287bU,733
|
|
10259
|
+
simo/fleet/migrations/__pycache__/0032_auto_20240415_0736.cpython-38.pyc,sha256=QD3JNIDQhzseXKLRYysYY3Q9_vDaurIhlWBcri83FMw,1655
|
|
10260
|
+
simo/fleet/migrations/__pycache__/0033_auto_20240415_0736.cpython-38.pyc,sha256=XBy2jZZ4kDRn06KC9YcHRnoaol8heCMAvHZ3BAELr2c,1031
|
|
10255
10261
|
simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6RnVPRq4CaO13Lg7M0F-pxA_gqqZ6Mg,170
|
|
10256
10262
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10257
10263
|
simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
|
|
@@ -10431,8 +10437,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10431
10437
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10432
10438
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10433
10439
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10434
|
-
simo-2.0.
|
|
10435
|
-
simo-2.0.
|
|
10436
|
-
simo-2.0.
|
|
10437
|
-
simo-2.0.
|
|
10438
|
-
simo-2.0.
|
|
10440
|
+
simo-2.0.7.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10441
|
+
simo-2.0.7.dist-info/METADATA,sha256=D3DwzzxRfVOdr1NCw4Me2MvxkgLnZ-jPQdbnREr0oV0,1699
|
|
10442
|
+
simo-2.0.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
10443
|
+
simo-2.0.7.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10444
|
+
simo-2.0.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|