simo 2.5.3__py3-none-any.whl → 2.5.4__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.

Files changed (47) hide show
  1. simo/core/__pycache__/app_widgets.cpython-38.pyc +0 -0
  2. simo/core/__pycache__/base_types.cpython-38.pyc +0 -0
  3. simo/core/__pycache__/controllers.cpython-38.pyc +0 -0
  4. simo/core/__pycache__/signal_receivers.cpython-38.pyc +0 -0
  5. simo/core/__pycache__/tasks.cpython-38.pyc +0 -0
  6. simo/core/app_widgets.py +19 -1
  7. simo/core/base_types.py +2 -0
  8. simo/core/controllers.py +154 -4
  9. simo/core/management/_hub_template/hub/supervisor.conf +4 -0
  10. simo/core/signal_receivers.py +8 -5
  11. simo/core/tasks.py +1 -1
  12. simo/fleet/__pycache__/controllers.cpython-38.pyc +0 -0
  13. simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
  14. simo/fleet/controllers.py +20 -119
  15. simo/fleet/forms.py +101 -0
  16. simo/generic/__pycache__/app_widgets.cpython-38.pyc +0 -0
  17. simo/generic/__pycache__/base_types.cpython-38.pyc +0 -0
  18. simo/generic/__pycache__/controllers.cpython-38.pyc +0 -0
  19. simo/generic/__pycache__/forms.cpython-38.pyc +0 -0
  20. simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
  21. simo/generic/app_widgets.py +0 -18
  22. simo/generic/base_types.py +0 -2
  23. simo/generic/controllers.py +2 -262
  24. simo/generic/forms.py +0 -49
  25. simo/generic/gateways.py +5 -118
  26. simo/generic/scripting/__pycache__/helpers.cpython-38.pyc +0 -0
  27. simo/generic/scripting/example.py +67 -0
  28. simo/generic/scripting/helpers.py +66 -10
  29. simo/users/__pycache__/admin.cpython-38.pyc +0 -0
  30. simo/users/__pycache__/api.cpython-38.pyc +0 -0
  31. simo/users/__pycache__/models.cpython-38.pyc +0 -0
  32. simo/users/admin.py +25 -5
  33. simo/users/api.py +25 -11
  34. simo/users/migrations/0035_instanceuser_last_seen_speed_kmh_and_more.py +23 -0
  35. simo/users/migrations/0036_instanceuser_phone_on_charge_user_phone_on_charge.py +23 -0
  36. simo/users/migrations/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.py +53 -0
  37. simo/users/migrations/__pycache__/0035_instanceuser_last_seen_speed_kmh_and_more.cpython-38.pyc +0 -0
  38. simo/users/migrations/__pycache__/0036_instanceuser_phone_on_charge_user_phone_on_charge.cpython-38.pyc +0 -0
  39. simo/users/migrations/__pycache__/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.cpython-38.pyc +0 -0
  40. simo/users/models.py +12 -55
  41. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/METADATA +1 -1
  42. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/RECORD +46 -40
  43. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/WHEEL +1 -1
  44. simo/scripting.py +0 -39
  45. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/LICENSE.md +0 -0
  46. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/entry_points.txt +0 -0
  47. {simo-2.5.3.dist-info → simo-2.5.4.dist-info}/top_level.txt +0 -0
Binary file
Binary file
simo/users/admin.py CHANGED
@@ -50,6 +50,20 @@ class PermissionsRoleAdmin(admin.ModelAdmin):
50
50
  return fields
51
51
 
52
52
 
53
+ @admin.register(InstanceUser)
54
+ class InstanceUserAdmin(admin.ModelAdmin):
55
+ list_display = (
56
+ 'user', 'role', 'is_active', 'at_home', 'last_seen', 'phone_on_charge'
57
+ )
58
+ fields = (
59
+ 'user', 'role', 'is_active', 'at_home', 'last_seen',
60
+ 'last_seen_location', 'last_seen_speed_kmh', 'phone_on_charge'
61
+ )
62
+ readonly_fields = (
63
+ 'at_home', 'last_seen', 'last_seen_speed_kmh', 'phone_on_charge',
64
+ )
65
+
66
+
53
67
  class InstanceUserInline(admin.TabularInline):
54
68
  model = InstanceUser
55
69
  extra = 0
@@ -69,7 +83,6 @@ class UserAdmin(OrgUserAdmin):
69
83
  fields = (
70
84
  'name', 'email', 'is_active', 'is_master',
71
85
  'ssh_key', 'secret_key',
72
- 'last_seen_location',
73
86
  )
74
87
  readonly_fields = (
75
88
  'name', 'email', 'avatar', 'last_action', 'is_active'
@@ -114,11 +127,18 @@ admin.site.unregister(Group)
114
127
 
115
128
 
116
129
  @admin.register(UserDeviceReportLog)
117
- class UserDeviceLogInline(admin.ModelAdmin):
130
+ class UserDeviceLog(admin.ModelAdmin):
118
131
  model = UserDeviceReportLog
119
- readonly_fields = 'datetime', 'app_open', 'location', 'relay', 'users'
120
- list_display = 'datetime', 'app_open', 'location', 'relay', 'users'
132
+ readonly_fields = (
133
+ 'datetime', 'app_open', 'location', 'relay', 'users',
134
+ 'speed_kmh', 'phone_on_charge'
135
+ )
136
+ list_display = (
137
+ 'datetime', 'app_open', 'location', 'relay', 'speed_kmh',
138
+ 'phone_on_charge', 'users'
139
+ )
121
140
  fields = readonly_fields
141
+ list_filter = 'user_device__users',
122
142
 
123
143
  def has_add_permission(self, request, obj=None):
124
144
  return False
@@ -142,7 +162,7 @@ class UserDeviceAdmin(admin.ModelAdmin):
142
162
  readonly_fields = (
143
163
  'users_display', 'token', 'os', 'last_seen',
144
164
  )
145
- fields = readonly_fields + ('last_seen_location', 'is_primary')
165
+ fields = readonly_fields + ('is_primary', )
146
166
 
147
167
  def get_queryset(self, request):
148
168
  qs = super().get_queryset(request)
simo/users/api.py CHANGED
@@ -8,6 +8,7 @@ from rest_framework.exceptions import ValidationError, PermissionDenied
8
8
  from django.contrib.gis.geos import Point
9
9
  from django.utils import timezone
10
10
  from django_filters.rest_framework import DjangoFilterBackend
11
+ from simo.conf import dynamic_settings
11
12
  from simo.core.api import InstanceMixin
12
13
  from .models import (
13
14
  User, UserDevice, UserDeviceReportLog, PermissionsRole, InstanceInvitation,
@@ -172,7 +173,7 @@ class UserDeviceReport(InstanceMixin, viewsets.GenericViewSet):
172
173
 
173
174
  @action(url_path='device-report', detail=False, methods=['post'])
174
175
  def report(self, request, *args, **kwargs):
175
-
176
+ from simo.generic.scripting.helpers import haversine_distance
176
177
  if not request.data.get('device_token'):
177
178
  return RESTResponse(
178
179
  {'status': 'error', 'msg': 'device_token - not provided'},
@@ -199,12 +200,23 @@ class UserDeviceReport(InstanceMixin, viewsets.GenericViewSet):
199
200
  except:
200
201
  location = None
201
202
 
203
+ relay = None
204
+ if request.META.get('HTTP_HOST', '').endswith('.simo.io'):
205
+ relay = request.META.get('HTTP_HOST')
206
+
207
+
202
208
  user_device.last_seen = timezone.now()
203
209
  if location:
204
210
  user_device.last_seen_location = ','.join(
205
211
  [str(i) for i in location]
206
212
  ) if location else None
207
213
 
214
+ speed_mps = float(request.data.get('speed', 0))
215
+ if speed_mps < 0:
216
+ speed_mps = 0
217
+ speed_kmh = speed_mps * 3.6
218
+
219
+
208
220
  if request.data.get('app_open', False):
209
221
  user_device.is_primary = True
210
222
  UserDevice.objects.filter(
@@ -213,23 +225,25 @@ class UserDeviceReport(InstanceMixin, viewsets.GenericViewSet):
213
225
  user_device.save()
214
226
 
215
227
  for iu in request.user.instance_roles.filter(is_active=True):
228
+ if location:
229
+ iu.at_home = haversine_distance(
230
+ iu.instance.location, user_device.last_seen_location
231
+ ) < dynamic_settings['users__at_home_radius']
232
+ elif not relay:
233
+ iu.at_home = True
234
+
235
+ iu.last_seen = user_device.last_seen
216
236
  iu.last_seen_location = user_device.last_seen_location
217
- iu.last_seen_location_datetime = user_device.last_seen
237
+ iu.last_seen_speed_kmh = speed_kmh
238
+ iu.phone_on_charge = request.data.get('is_charging', False)
218
239
  iu.save()
219
240
 
220
- request.user.last_seen_location = user_device.last_seen_location
221
- request.user.last_seen_location_datetime = user_device.last_seen
222
- request.user.save()
223
-
224
- relay = None
225
- if request.META.get('HTTP_HOST', '').endswith('.simo.io'):
226
- relay = request.META.get('HTTP_HOST')
227
-
228
241
  UserDeviceReportLog.objects.create(
229
242
  user_device=user_device, instance=self.instance,
230
243
  app_open=request.data.get('app_open', False),
231
244
  location=','.join([str(i) for i in location]) if location else None,
232
- relay=relay
245
+ relay=relay, speed_kmh=speed_kmh,
246
+ phone_on_charge=request.data.get('is_charging', False)
233
247
  )
234
248
 
235
249
  return RESTResponse({'status': 'success'})
@@ -0,0 +1,23 @@
1
+ # Generated by Django 4.2.10 on 2024-10-29 07:38
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('users', '0034_instanceuser_last_seen_location_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='instanceuser',
15
+ name='last_seen_speed_kmh',
16
+ field=models.FloatField(default=0),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='user',
20
+ name='last_seen_speed_kmh',
21
+ field=models.FloatField(default=0),
22
+ ),
23
+ ]
@@ -0,0 +1,23 @@
1
+ # Generated by Django 4.2.10 on 2024-10-29 12:58
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('users', '0035_instanceuser_last_seen_speed_kmh_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='instanceuser',
15
+ name='phone_on_charge',
16
+ field=models.BooleanField(db_index=True, default=False),
17
+ ),
18
+ migrations.AddField(
19
+ model_name='user',
20
+ name='phone_on_charge',
21
+ field=models.BooleanField(db_index=True, default=False),
22
+ ),
23
+ ]
@@ -0,0 +1,53 @@
1
+ # Generated by Django 4.2.10 on 2024-10-29 13:23
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('users', '0036_instanceuser_phone_on_charge_user_phone_on_charge'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='instanceuser',
15
+ old_name='last_seen_location_datetime',
16
+ new_name='last_seen',
17
+ ),
18
+ migrations.RemoveField(
19
+ model_name='user',
20
+ name='last_seen_location',
21
+ ),
22
+ migrations.RemoveField(
23
+ model_name='user',
24
+ name='last_seen_location_datetime',
25
+ ),
26
+ migrations.RemoveField(
27
+ model_name='user',
28
+ name='last_seen_speed_kmh',
29
+ ),
30
+ migrations.RemoveField(
31
+ model_name='user',
32
+ name='phone_on_charge',
33
+ ),
34
+ migrations.RemoveField(
35
+ model_name='userdevice',
36
+ name='last_seen_location',
37
+ ),
38
+ migrations.AddField(
39
+ model_name='userdevicereportlog',
40
+ name='phone_on_charge',
41
+ field=models.BooleanField(db_index=True, default=False),
42
+ ),
43
+ migrations.AddField(
44
+ model_name='userdevicereportlog',
45
+ name='speed_kmh',
46
+ field=models.FloatField(default=0),
47
+ ),
48
+ migrations.AlterField(
49
+ model_name='userdevice',
50
+ name='last_seen',
51
+ field=models.DateTimeField(auto_now=True, db_index=True),
52
+ ),
53
+ ]
simo/users/models.py CHANGED
@@ -97,17 +97,22 @@ class InstanceUser(DirtyFieldsMixin, models.Model, OnChangeMixin):
97
97
  related_name='instance_users',
98
98
  )
99
99
  role = models.ForeignKey(PermissionsRole, on_delete=models.CASCADE)
100
- at_home = models.BooleanField(default=False, db_index=True)
101
100
  is_active = models.BooleanField(default=True, db_index=True)
101
+
102
+ at_home = models.BooleanField(default=False, db_index=True)
103
+ last_seen = models.DateTimeField(
104
+ null=True, blank=True,
105
+ )
102
106
  last_seen_location = PlainLocationField(
103
107
  zoom=7, null=True, blank=True, help_text="Sent by user mobile app"
104
108
  )
105
- last_seen_location_datetime = models.DateTimeField(
106
- null=True, blank=True,
107
- )
109
+ last_seen_speed_kmh = models.FloatField(default=0)
110
+ phone_on_charge = models.BooleanField(default=False, db_index=True)
108
111
 
109
112
  objects = ActiveInstanceManager()
110
113
 
114
+ on_change_fields = ('last_seen',)
115
+
111
116
  class Meta:
112
117
  unique_together = 'user', 'instance'
113
118
 
@@ -175,12 +180,6 @@ class User(AbstractBaseUser, SimoAdminMixin):
175
180
  help_text="Will be placed in /root/.ssh/authorized_keys "
176
181
  "if user is active and is master of a hub."
177
182
  )
178
- last_seen_location = PlainLocationField(
179
- zoom=7, null=True, blank=True, help_text="Sent by user mobile app"
180
- )
181
- last_seen_location_datetime = models.DateTimeField(
182
- null=True, blank=True,
183
- )
184
183
  secret_key = models.CharField(
185
184
  max_length=20, db_index=True, default=get_random_string
186
185
  )
@@ -422,8 +421,7 @@ class UserDevice(models.Model, SimoAdminMixin):
422
421
  os = models.CharField(max_length=100, db_index=True)
423
422
  token = models.CharField(max_length=1000, db_index=True, unique=True)
424
423
  is_primary = models.BooleanField(default=True, db_index=True)
425
- last_seen = models.DateTimeField(auto_now_add=True, db_index=True)
426
- last_seen_location = PlainLocationField(zoom=7, null=True, blank=True)
424
+ last_seen = models.DateTimeField(auto_now=True, db_index=True)
427
425
 
428
426
  class Meta:
429
427
  ordering = '-last_seen',
@@ -445,54 +443,13 @@ class UserDeviceReportLog(models.Model):
445
443
  help_text="Sent via remote relay if specified, otherwise it's from LAN."
446
444
  )
447
445
  location = PlainLocationField(zoom=7, null=True, blank=True)
446
+ speed_kmh = models.FloatField(default=0)
447
+ phone_on_charge = models.BooleanField(default=False, db_index=True)
448
448
 
449
449
  class Meta:
450
450
  ordering = '-datetime',
451
451
 
452
452
 
453
- @receiver(post_save, sender=UserDeviceReportLog)
454
- def set_user_at_home(sender, instance, created, **kwargs):
455
- from simo.core.models import Instance
456
- if not created:
457
- return
458
-
459
- if not instance.location and not instance.relay:
460
- for item in InstanceUser.objects.filter(
461
- user__in=instance.user_device.users.all()
462
- ):
463
- item.at_home = True
464
- item.save()
465
- return
466
-
467
- for hub_instance in Instance.objects.filter(is_active=True):
468
- try:
469
- instance_location = Point(
470
- [float(hub_instance.location.split(',')[0]),
471
- float(hub_instance.location.split(',')[1])],
472
- srid=4326
473
- )
474
- except:
475
- return
476
- try:
477
- log_location = Point(
478
- [
479
- float(instance.location.split(',')[0]),
480
- float(instance.location.split(',')[1])
481
- ], srid=4326
482
- )
483
- except:
484
- return
485
- else:
486
- for item in InstanceUser.objects.filter(
487
- user__in=instance.user_device.users.all(),
488
- instance=hub_instance
489
- ):
490
- item.at_home = distance(
491
- instance_location, log_location
492
- ).meters < dynamic_settings['users__at_home_radius']
493
- item.save()
494
-
495
-
496
453
  class ComponentPermission(models.Model):
497
454
  role = models.ForeignKey(
498
455
  PermissionsRole, on_delete=models.CASCADE,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.5.3
3
+ Version: 2.5.4
4
4
  Summary: Smart Home on Steroids!
5
5
  Author-email: Simanas Venčkauskas <simanas@simo.io>
6
6
  Project-URL: Homepage, https://simo.io
@@ -2,7 +2,6 @@ simo/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
2
2
  simo/asgi.py,sha256=L8CUVZLM32IMzWDZ4IShdDN-m69t7oxAUeHods4-xNM,822
3
3
  simo/celeryc.py,sha256=eab7_e9rw0c__DCeoUFUh_tjAGVlulxVrk75BaJf57Q,1512
4
4
  simo/conf.py,sha256=H2BhXAV8MEDVXF8AbkaLSfR4ULd-9_bS4bnhE5sE5fg,112
5
- simo/scripting.py,sha256=ixgi6mKzxHJD5d9-TDl4YhG9n8dZWIoCFNzku_I648g,931
6
5
  simo/settings.py,sha256=BcirAAKau1KiJ5qKTD0ni8hTk3jHAASBcUCBNZPGNCk,6962
7
6
  simo/urls.py,sha256=fRmAsNQ_pzFloimLmxNeDcR6hHRJ3rOoZ3kGy8zOQ_A,2402
8
7
  simo/__pycache__/__init__.cpython-38.pyc,sha256=j81de0BqHMr6bs0C7cuYrXl7HwtK_vv8hDEtAdSwDJc,153
@@ -37,13 +36,13 @@ simo/core/admin.py,sha256=5mi0Qe9TM-OILCxbcRfGJvq397QCPxjYX30K3CIZrPs,18133
37
36
  simo/core/api.py,sha256=A8P47OFFcqw-AXQPF3XqIV3pshEyqQGwLdM8aByddns,28288
38
37
  simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
39
38
  simo/core/api_meta.py,sha256=EaiY-dCADP__9MvLpoHvhjytFT92IrxPZDv95xgqasU,4955
40
- simo/core/app_widgets.py,sha256=ReWXLolUX6xW7QgB_qXTrrYyNvzustj9tXCXnUyCvJ8,2224
39
+ simo/core/app_widgets.py,sha256=VxZzapuc-a29wBH7JzpvNF2SK1ECrgNUySId5ke1ffc,2509
41
40
  simo/core/apps.py,sha256=CsqpiQerhmrMsH-wGiG-gQgXd9qEkIi-LUaA9cXpKSw,425
42
41
  simo/core/auto_urls.py,sha256=nNXEgLAAAQAhRWQDA9AbDtw-zcPKmu_pufJaSa8g818,1102
43
42
  simo/core/autocomplete_views.py,sha256=JT5LA2_Wtr60XYSAIqaXFKFYPjrmkEf6yunXD9y2zco,4022
44
- simo/core/base_types.py,sha256=qVh6MrXZEfN7bFOyFftC7u0yyz0PkvpsjllLBc6SCp4,616
43
+ simo/core/base_types.py,sha256=WypW8hTfzveuTQtruGjLYAGQZIuczxTlW-SdRk3iQug,666
45
44
  simo/core/context.py,sha256=snfPIGcZQTrx8iiZc5PI91A0dRQH6y5kH4uG_lfhU6Q,1486
46
- simo/core/controllers.py,sha256=JeOvn1Y4MYGkimqEB_6u3B-KwJk3qLjY63ELlFXih14,30027
45
+ simo/core/controllers.py,sha256=JvXdwXD7iotA7fIjZmBVshKLQGSt9Na48FMAyHRDh84,35615
47
46
  simo/core/dynamic_settings.py,sha256=bUs58XEZOCIEhg1TigR3LmYggli13KMryBZ9pC7ugAQ,1872
48
47
  simo/core/events.py,sha256=fH6d5HcPdDqT3R7CZPdo69qTszJ23j3GJt3IFOso3WA,4757
49
48
  simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
@@ -57,10 +56,10 @@ simo/core/models.py,sha256=fEbRVY128-FdjG2ueQhBlSMRpvKcxY2VKCJUqXsSMPI,22441
57
56
  simo/core/permissions.py,sha256=v0iJM4LOeYoEfMiw3OLPYio272G1aUEAg_z9Wd1q5m0,2993
58
57
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
59
58
  simo/core/serializers.py,sha256=Pa2lhJ6VgNalbH4awbKdGJCYAPNsu5WQWfo6Tz6LbOQ,20782
60
- simo/core/signal_receivers.py,sha256=9-qFCCeSLcMFEMg6QUtKOVgUsoNoqhzGoI98nuNSTEo,6228
59
+ simo/core/signal_receivers.py,sha256=Mt3bDLEIO3ygqG9fCiObJ3oPv4P1F4NAjiqo5sbmY6g,6248
61
60
  simo/core/socket_consumers.py,sha256=trRZvBGTJ7xIbfdmVvn7zoiWp_qssSkMZykDrI5YQyE,9783
62
61
  simo/core/storage.py,sha256=_5igjaoWZAiExGWFEJMElxUw55DzJG1jqFty33xe8BE,342
63
- simo/core/tasks.py,sha256=wYCaARytOqnBkoZ1zV59yCtZBqmu3Sd-eNpyZsv4LW0,14572
62
+ simo/core/tasks.py,sha256=dLutVjQdAhZVFldQpWilQEYfPcTFqkAoyGao0MTuKJ0,14583
64
63
  simo/core/todos.py,sha256=eYVXfLGiapkxKK57XuviSNe3WsUYyIWZ0hgQJk7ThKo,665
65
64
  simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
66
65
  simo/core/views.py,sha256=3SRZr00fyLQf8ja3U-9eekKt-ld5TvU1WQqUWprXfQ4,2390
@@ -70,13 +69,13 @@ simo/core/__pycache__/admin.cpython-38.pyc,sha256=uM58xiBAbbstmKZ0CoxLSk_RRu5TDV
70
69
  simo/core/__pycache__/api.cpython-38.pyc,sha256=OFl3_PMd48Is0ohUEXeN-eQv_V2oAlphKyWS4FzKGhY,21862
71
70
  simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=6M9Cl_ha4y_Vf8Rv4GMYL8dcBCmp0KzYi6jn3SQTgys,1712
72
71
  simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=VYx5ZeDyNBI4B_CBEIhV5B3GnLsMOx9s3rNZTSMODco,3703
73
- simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=fmZhynYrx5X5gidhXovhnf8-FdbCLfUB9NS_lpHBF3s,3830
72
+ simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=oN657XMMZ6GYN9nblv7fX3kdnTEzSP9XV6PXM6Z0wl4,4358
74
73
  simo/core/__pycache__/apps.cpython-38.pyc,sha256=JL0BEqgXcSQvMlcK48PBpPfyDEkPMdO1Y0teqMRGirs,713
75
74
  simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=Tyf8PYHq5YqSwTp25Joy-eura_Fm86fpX9zKLSklhvo,872
76
75
  simo/core/__pycache__/autocomplete_views.cpython-38.pyc,sha256=hJ6JILI1LqrAtpQMvxnLvljGdW1v1gpvBsD79vFkZ58,3972
77
- simo/core/__pycache__/base_types.cpython-38.pyc,sha256=hmq22vvGyCmhbYyuV6bFAOOSIupspgW5yq_VzqWd-vY,759
76
+ simo/core/__pycache__/base_types.cpython-38.pyc,sha256=CX-qlF7CefRi_mCE954wYa9rUFR88mOl6g7fybDRu7g,803
78
77
  simo/core/__pycache__/context.cpython-38.pyc,sha256=ck1FcBljLB4__5F6poS2tEEn8IDDgK7pU3FcXDPc_mI,1329
79
- simo/core/__pycache__/controllers.cpython-38.pyc,sha256=ycGGRvBwNsOl2obNKl5t77UK5mkn8bEU4_1dE0K_Z9k,26897
78
+ simo/core/__pycache__/controllers.cpython-38.pyc,sha256=s7onEMtWmHjvTGvWXIbpvWMWb7aAfOVhFhWuu49kLSg,30701
80
79
  simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=wGpnscX1DxFpRl54MQURhjz2aD3NJohSzw9JCFnzh2Y,2384
81
80
  simo/core/__pycache__/events.cpython-38.pyc,sha256=yip7WSyX4pUy2wJE820W4fD7iwoIWGhdHfloFb_N0R8,5257
82
81
  simo/core/__pycache__/filters.cpython-38.pyc,sha256=VIMADCBiYhziIyRmxAyUDJluZvuZmiC4bNYWTRsGSao,721
@@ -90,10 +89,10 @@ simo/core/__pycache__/models.cpython-38.pyc,sha256=vq7ysMUjqPdcPl6DfLzAzmJWPC9_W
90
89
  simo/core/__pycache__/permissions.cpython-38.pyc,sha256=fH4iyqd9DdzRLEu2b621-FeM-napR0M7hzBUTHo9Q3g,2972
91
90
  simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
92
91
  simo/core/__pycache__/serializers.cpython-38.pyc,sha256=qIHxrurPk555mHc9P8Udg9eGv-ODw1FTmBS_jXrPuws,19220
93
- simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=3Bt9S47DR_ZFS3O-crElFgLLXPIYyDgPIc2ibwEkaic,4904
92
+ simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=MoIxnq-Eny7Ob-9Afv6ue7htA5Di-UoohprHosR6Z_U,4903
94
93
  simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=KqbO1cOewodVPcy0-htVefyUjCuELKV0o7fOfYqfgPc,8490
95
94
  simo/core/__pycache__/storage.cpython-38.pyc,sha256=9R1Xu0FJDflfRXUPsqEgt0SpwiP7FGk7HaR8s8XRyI8,721
96
- simo/core/__pycache__/tasks.cpython-38.pyc,sha256=HCp_TnVN3_q7WlAXrLbTbux30OG0hyTOqOHYvqcz1hU,9989
95
+ simo/core/__pycache__/tasks.cpython-38.pyc,sha256=qQZ1wP3ksyh6c6kmqMtkYxGs-MTTDhaqQDlYfK7vQ7c,10003
97
96
  simo/core/__pycache__/todos.cpython-38.pyc,sha256=lOqGZ58siHM3isoJV4r7sg8igrfE9fFd-jSfeBa0AQI,253
98
97
  simo/core/__pycache__/views.cpython-38.pyc,sha256=K_QM967bIJeU02DJu0Dm7j8RiFDKn_TLzX77YzNkA7c,2495
99
98
  simo/core/__pycache__/widgets.cpython-38.pyc,sha256=sR0ZeHCHrhnNDBJuRrxp3zUsfBp0xrtF0xrK2TkQv1o,3520
@@ -154,7 +153,7 @@ simo/core/management/_hub_template/hub/celeryc.py,sha256=3ksDXftIZKJ4Cq9WNKJERdZ
154
153
  simo/core/management/_hub_template/hub/manage.py,sha256=PNNlw3EVeIJDgkG0l-klqoxsKWfTYWG9jzRG0upmAaI,620
155
154
  simo/core/management/_hub_template/hub/nginx.conf,sha256=40hvXL42MeiqqkLURNcDQsRudv1dNFLJnvb2-Y3RCkk,2394
156
155
  simo/core/management/_hub_template/hub/settings.py,sha256=4QhvhbtLRxHvAntwqG_qeAAtpDUqKvN4jzw9u3vqff8,361
157
- simo/core/management/_hub_template/hub/supervisor.conf,sha256=MOsMo8QjBKUl5EUWG4GrA6BjLc4s7pU17xAKY2uGjZU,1938
156
+ simo/core/management/_hub_template/hub/supervisor.conf,sha256=6WemJ19T-mLiVGkQdfBxD3Y7UhU6exT0jizOwg2VQAk,2006
158
157
  simo/core/management/_hub_template/hub/urls.py,sha256=Ydm-1BkYAzWeEF-MKSDIFf-7aE4qNLPm48-SA51XgJQ,25
159
158
  simo/core/management/_hub_template/hub/wsgi.py,sha256=Lo-huLHnMDTxSmMBOodVFMWBls9poddrV2KRzXU0xGo,280
160
159
  simo/core/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -10220,8 +10219,8 @@ simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
10220
10219
  simo/fleet/auto_urls.py,sha256=UX66eR2ykMqFgfIllW-RTdjup5-FieCWl_BVm3CcXKg,702
10221
10220
  simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
10222
10221
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10223
- simo/fleet/controllers.py,sha256=i1GwbT6apIvdyfuVQYNkliBNlKmffCOdpjall3o3NxQ,32735
10224
- simo/fleet/forms.py,sha256=yyb9KhhqbcfBBXh5PbzKH1uKP2ZH-LW6UZXD9AwT7rw,59079
10222
+ simo/fleet/controllers.py,sha256=fjri1GtCnflkkDpNqhTwy6i9CK6RDEB0Q_BtADzcG8E,29156
10223
+ simo/fleet/forms.py,sha256=XTkQUxce-6VPr7-HRONJnIzWZizeIUeA6DGqqTACInQ,62980
10225
10224
  simo/fleet/gateways.py,sha256=lKEJW0MgaOEiNnijH50DNSVChvaUT3TA3UurcI57P8k,5677
10226
10225
  simo/fleet/managers.py,sha256=XOpDOA9L-f_550TNSyXnJbun2EmtGz1TenVTMlUSb8E,807
10227
10226
  simo/fleet/models.py,sha256=eaXuUdiK9LnBFHARcR9sC049It1s6OrPTWVmysfQyYg,16812
@@ -10237,8 +10236,8 @@ simo/fleet/__pycache__/api.cpython-38.pyc,sha256=rL9fb7cCQatyFvXyKmlNOKmxVo8vHYe
10237
10236
  simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=Tc6a6BCXHjijP8U2jE2ghlJwnSNrGm59-hW5t-80wF0,689
10238
10237
  simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
10239
10238
  simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
10240
- simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=K_UMv4Vnc1JBd7GHIekm_6YBHApWONFBql5Plnm73nw,26901
10241
- simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=IRHNJ4RXP17cm9jcZdf96YCeV-AMeVDgvFA8isgiC2E,40489
10239
+ simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=jtFHr_uyjCCeuidL-o-hGaf21u0fnxK_O6hTRdY6lpc,24906
10240
+ simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=8ARAilbCnSUjwluL0mmknFcNvBRn8oZ7b2-z8Yer6ns,42498
10242
10241
  simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=0RKVn0ndreVKhsrukqeLPSdMnRrsQ_W7yeVeBkRLfIk,5058
10243
10242
  simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=8uz-xpUiqbGDgXIZ_XRZtFb-Tju6NGxflGg-Ee4Yo6k,1310
10244
10243
  simo/fleet/__pycache__/models.cpython-38.pyc,sha256=am7ceraEUIJPD5qO3y-_X1riXIYsZGYZOlZmGjqhy7g,13906
@@ -10333,28 +10332,29 @@ simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6Rn
10333
10332
  simo/fleet/templates/fleet/controllers_info/Button.md,sha256=GIuxqG617174NEtpPeCGVocxO4YMe7-CacgVSu_L5-E,739
10334
10333
  simo/fleet/templates/fleet/controllers_info/ENS160AirQualitySensor.md,sha256=3LSTY9YPFuVPIbVsYCAifcotrXJcOXl2k774_vo6nAE,770
10335
10334
  simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10336
- simo/generic/app_widgets.py,sha256=E_pnpA1hxMIhenRCrHoQ5cik06jm2BAHCkl_eo-OudU,1264
10337
- simo/generic/base_types.py,sha256=djymox_boXTHX1BTTCLXrCH7ED-uAsV_idhaDOc3OLI,409
10338
- simo/generic/controllers.py,sha256=NQelUJhAVsPH88RRiX4D0-NBb3pwwXcF2orMVdfneic,59918
10339
- simo/generic/forms.py,sha256=GuB-5H-GX9_2Q-YjwrHVcryTDo5CuJb3rsFG7-mMr5A,32759
10340
- simo/generic/gateways.py,sha256=JaX-wVaYh3CTkryq-Lq_UQfA4JWdxY42QkchstC12Sw,18982
10335
+ simo/generic/app_widgets.py,sha256=vwYYVRKzKZ9XTvWTfEbaH4zpoHiDIHP6qFTNgZI-xvY,979
10336
+ simo/generic/base_types.py,sha256=Bvf3lv6PXx_SwtwBH7qpkwysWuloNcKNRh3LiuZf-Dc,359
10337
+ simo/generic/controllers.py,sha256=Xo0ZYQZfhDAwLq9H3uTrHWLj-HeLlxdXJ71dUESd41Y,49263
10338
+ simo/generic/forms.py,sha256=nDrvNGbWTE_MSZmSXrKj1bSn-Ylo4w7Y1z-SZRKRYW8,30840
10339
+ simo/generic/gateways.py,sha256=n7r0-frVzBw0vmXBQXaaq4TfdaJmUhaAstcIIBls3xM,15129
10341
10340
  simo/generic/models.py,sha256=YEAFfkARsAellfDwmmqGSx7nKkEF5XngciRB4qP1MKk,7596
10342
10341
  simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
10343
10342
  simo/generic/socket_consumers.py,sha256=K2OjphIhKJH48BvfFfoCOyCQZ1NmXb_phs6y1IP-qaQ,1757
10344
10343
  simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=mLu54WS9KIl-pHwVCBKpsDFIlOqml--JsOVzAUHg6cU,161
10345
- simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=0IoKRG9n1tkNRRkrqAeOQwWBPd_33u98JBcVtMVVCio,2374
10346
- simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=ptw6axyAqemZA35oa6vzr7EihzvbhW9w7Y-G6kfDedU,555
10347
- simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=QrZsXgBvwrlGtI0PwQAl8TFDD5RAkm3mjIvfmJSpbq8,37734
10348
- simo/generic/__pycache__/forms.cpython-38.pyc,sha256=BS9XscqbEcTPIr6kzZzpya2SCgqiGkLGXWiACt0_IFo,23316
10349
- simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=H5cK5eNQ6P24wSmoRUKvVhkggrKEJ1UGiCkQQ5g98xI,14073
10344
+ simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=dt7fSf38eDA5hVUvVfpytOKoAFLQJuFffoAfqhJUKNc,1846
10345
+ simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=8YDxrsRFGqaeBfSF3Y1WmIGDRHGH1Ww7dSBkxRxkKyc,511
10346
+ simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=HBZDEFhJAwd6YFWul_sX4OoA1r1m0DK1MLxJk9u70rk,32674
10347
+ simo/generic/__pycache__/forms.cpython-38.pyc,sha256=JM1UN13391udDpBvNsbZURX5onDhLrOLIun-kISmGac,22078
10348
+ simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=_TW6l2HyTBH5e_m_r6yGYcPfuULyE4XuVCFLS7upOWA,11544
10350
10349
  simo/generic/__pycache__/models.cpython-38.pyc,sha256=ES8wXkdKn0m-yaJlvhyaIOSppuX9Ckz-bOs9DCpVvaQ,5825
10351
10350
  simo/generic/__pycache__/routing.cpython-38.pyc,sha256=xtxTUTBTdivzFyA5Wh7k-hUj1WDO_FiRq6HYXdbr9Ks,382
10352
10351
  simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=qJO5kvQLWhsQDOr1AtAtsAybuRWioxSkQei3Pc7rdP0,1737
10353
10352
  simo/generic/scripting/__init__.py,sha256=aZZvNBae7unnux_zGHCIWCV2z47hVJc-DIL72Hqfkeo,600
10354
- simo/generic/scripting/helpers.py,sha256=cuJ7B79auIw6CmgkcPoQsJekUPIXq00ucneRALdPWwE,919
10353
+ simo/generic/scripting/example.py,sha256=2maqEIFYgWHSSPdBfYidlNCUEH1fcxUztcjUk5fdqUg,2306
10354
+ simo/generic/scripting/helpers.py,sha256=Zt8Mx5AXIggzYk0e7jn-xQNR_NOqzolAReLkrmDJzVQ,3042
10355
10355
  simo/generic/scripting/serializers.py,sha256=PjyFrjdPK1mBsgbNhyqMi9SWzcymqTa742ipy0LhAN4,1996
10356
10356
  simo/generic/scripting/__pycache__/__init__.cpython-38.pyc,sha256=eHncoNpv5dy35IO1_htWd8CK0sHFBnU_WJ0hl5TKOHQ,794
10357
- simo/generic/scripting/__pycache__/helpers.cpython-38.pyc,sha256=S8uwKmMjF9ySsm6xQrDSP6bOA0_IcYyfqluA-qtWfNo,1410
10357
+ simo/generic/scripting/__pycache__/helpers.cpython-38.pyc,sha256=JPBjYr6K6DbXBx82FOvQ8cRNy4zm_g160MrTvA12cNQ,2124
10358
10358
  simo/generic/scripting/__pycache__/serializers.cpython-38.pyc,sha256=JD9KCNO27H18mkFaeSMdybTMdTvodqcZSLNbC3pheHU,3412
10359
10359
  simo/generic/static/weather_icons/01d@2x.png,sha256=TZfWi6Rfddb2P-oldWWcjUiuCHiU9Yrc5hyrQAhF26I,948
10360
10360
  simo/generic/static/weather_icons/01n@2x.png,sha256=e9RleTa0T7To9Wi2wJ-9waeTbfHOsUB_xGwkx-89eEg,945
@@ -10430,15 +10430,15 @@ simo/notifications/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=YnO
10430
10430
  simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-38.pyc,sha256=Gkb3Qwr_zglGibQg9g5ekIgxtGapS4ENXVWQVHqM56I,794
10431
10431
  simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=YMBRHVon2nWDtIUbghckjnC12sIg_ykPWhV5aM0tto4,178
10432
10432
  simo/users/__init__.py,sha256=6a7uBpCWB_DR7p54rbHusc0xvi1qfT1ZCCQGb6TiBh8,52
10433
- simo/users/admin.py,sha256=oaLFTrjDaruKC_l79BB0etru4p8nP8eJFV3F4TSYGp4,6305
10434
- simo/users/api.py,sha256=MoURNgcdGl5eS881SbO5nw-zgwSEnbXzb-FrOyA7Vbc,11599
10433
+ simo/users/admin.py,sha256=Xr7faGeupUKkpo1QLRm84OS63u-5Rf2ir_nVEaAPBZw,6839
10434
+ simo/users/api.py,sha256=2AOt-IoG2MaOnq9XgWBpeT0ViszKZXKGUb-VmPdX7uI,12141
10435
10435
  simo/users/apps.py,sha256=cq0A8-U1HALEwev0TicgFhr4CAu7Icz8rwq0HfOaL4E,207
10436
10436
  simo/users/auth_backends.py,sha256=bBSNXQJ88TRXaQxyh1aETfmOIfiDr08Jnj8rSY9sHDk,4074
10437
10437
  simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
10438
10438
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10439
10439
  simo/users/managers.py,sha256=Fajwpm3wdMES73iPqoa_66J8g13bvUhjUtrexLKIcIU,312
10440
10440
  simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
10441
- simo/users/models.py,sha256=xzkLAspcHL0D3kdukEKOwdr4QuLFbocuxkr0BZaJHS4,20590
10441
+ simo/users/models.py,sha256=X6xrCbsS22N_bWwTNH4r-zXQV0MoVzcthz3b8KlyQdw,19185
10442
10442
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10443
10443
  simo/users/serializers.py,sha256=zzw1KONTnaTNBaU0r4rNVxJ827KzD6Z5LuQt27ZsQ98,2516
10444
10444
  simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
@@ -10447,15 +10447,15 @@ simo/users/tasks.py,sha256=HJAqiyWGsaN3wSfquU0UyQ20jL-njXeaaTOdDT3TQ3s,979
10447
10447
  simo/users/utils.py,sha256=1HGSZyHRqQvdJ4RtAiZDg1juvgG8aOlrGXR7CcvsyQc,1886
10448
10448
  simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
10449
10449
  simo/users/__pycache__/__init__.cpython-38.pyc,sha256=VFoDJE_SKKaPqqYaaBYd1Ndb1hjakkTo_u0EG_XJ1GM,211
10450
- simo/users/__pycache__/admin.cpython-38.pyc,sha256=UgkqzfrSQU8Hyqig03Z5Qq29434wU27ttufxtvGEJYw,7433
10451
- simo/users/__pycache__/api.cpython-38.pyc,sha256=ptN4kOcpA185pPGbU70aVbZQmzr8myOuAndzqXaKZKk,9852
10450
+ simo/users/__pycache__/admin.cpython-38.pyc,sha256=tL8b3f181AjcN2dSsDUPkqjpZziEOtVzI535SbnbDzc,7793
10451
+ simo/users/__pycache__/api.cpython-38.pyc,sha256=lXK7f-8loDkhuppb1RAWyKxV6-jRE-ZvCyqJDu4Hgug,10224
10452
10452
  simo/users/__pycache__/apps.cpython-38.pyc,sha256=dgbWL8CxzzISJQTmq_4IztPJ2UzykNVdqA2Ae1PmeGk,605
10453
10453
  simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=n5nx2QSXNj2idzRcGE6bAagMN-8qxoCs580H1EFZXls,3105
10454
10454
  simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=K-3sz2h-cEitoflSmZk1t0eUg5mQMMGLNZFREVwG7_o,430
10455
10455
  simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
10456
10456
  simo/users/__pycache__/managers.cpython-38.pyc,sha256=8NvEXbI795f-BXs6CvE_Kp0PpWfYmEJIZ8Bh8H6S2PQ,705
10457
10457
  simo/users/__pycache__/middleware.cpython-38.pyc,sha256=Tj4nVEAvxEW3xA63fBRiJWRJpz_M848ZOqbHioc_IPE,1149
10458
- simo/users/__pycache__/models.cpython-38.pyc,sha256=ZPwHo7woKL0Tlj3q8MWHeqFKpvh1AKkAslrjr8860to,18550
10458
+ simo/users/__pycache__/models.cpython-38.pyc,sha256=kqpXK10DZ7C4UrR_LblK5Y1y8Mp3-0mNo6-IZSF6I9w,17844
10459
10459
  simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
10460
10460
  simo/users/__pycache__/serializers.cpython-38.pyc,sha256=Dy8RAcwNkNSXoJHvLp8fozURyHCtucqpSPyqZtbnMZc,3732
10461
10461
  simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=uAwDozpOmrhUald-8tOHANILXkH7-TI8fNYXOtPkSY8,402
@@ -10497,6 +10497,9 @@ simo/users/migrations/0031_auto_20240923_1115.py,sha256=RyhmpsxpSXK9Ejbh3cHm9fTn
10497
10497
  simo/users/migrations/0032_remove_userdevice_user_alter_userdevice_users.py,sha256=pM0B4ghsw6LWDvT_9owUmqIHQiraauTGYm_EePhVBUQ,570
10498
10498
  simo/users/migrations/0033_alter_user_ssh_key.py,sha256=yR7rI2K3FThEp6zEXWx29Zej4HzG5QufKPcj-m8pFuE,519
10499
10499
  simo/users/migrations/0034_instanceuser_last_seen_location_and_more.py,sha256=_W7qUsVosxBgeQ4oogfJiDryNnGbQTWiusrDVW70JZU,716
10500
+ simo/users/migrations/0035_instanceuser_last_seen_speed_kmh_and_more.py,sha256=lAtNHugmvm-ssNL3R82o2mKayxBU5K_wLXoWaxyr1XI,580
10501
+ simo/users/migrations/0036_instanceuser_phone_on_charge_user_phone_on_charge.py,sha256=uHXLRmFAASdB9sPivYkRu7WV4rxZDI3RaEwl2i7U_xg,615
10502
+ simo/users/migrations/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.py,sha256=8f_7fC7k0Dm-0gGVHMI9_490BbEC_SfuAPrAADrZ7BA,1543
10500
10503
  simo/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10501
10504
  simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=e4XOKaYRb7l0P7cBnHHi5FQQJMlwjK0g7iqgM-xKmNI,4215
10502
10505
  simo/users/migrations/__pycache__/0002_componentpermission.cpython-38.pyc,sha256=pknJnpic8p6Vdx9DX41FfODXNnvexDswJtUCmC5w1tg,995
@@ -10534,6 +10537,9 @@ simo/users/migrations/__pycache__/0031_auto_20240923_1115.cpython-38.pyc,sha256=
10534
10537
  simo/users/migrations/__pycache__/0032_remove_userdevice_user_alter_userdevice_users.cpython-38.pyc,sha256=SDKPEIkt9DYEBRm63GAnxG1yRKKm-JP3pizaJdbAUks,772
10535
10538
  simo/users/migrations/__pycache__/0033_alter_user_ssh_key.cpython-38.pyc,sha256=HCdJw3La6yFkA9v8QcTMAKub_BKhqIH6U4lVY8G4JII,733
10536
10539
  simo/users/migrations/__pycache__/0034_instanceuser_last_seen_location_and_more.cpython-38.pyc,sha256=YHxGkhAaI2Es3OK61kdNWViyM7UlEiuFGOV5oAyaL_E,871
10540
+ simo/users/migrations/__pycache__/0035_instanceuser_last_seen_speed_kmh_and_more.cpython-38.pyc,sha256=EOQ0J-t-CMgyVCAl6NHBXyScx6D83MO-zISO9Z1aE-U,705
10541
+ simo/users/migrations/__pycache__/0036_instanceuser_phone_on_charge_user_phone_on_charge.cpython-38.pyc,sha256=y1ZDJ8VM5_vJOxTPRERjwukiGXJ89UhDc4bHiHZwQ_w,723
10542
+ simo/users/migrations/__pycache__/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.cpython-38.pyc,sha256=W4Rc6SRNNJ_yAYrEyoklD5LFmQPAL9mTDrXHMfP8R4I,1162
10537
10543
  simo/users/migrations/__pycache__/__init__.cpython-38.pyc,sha256=NKq7WLgktK8WV1oOqCPbAbdkrPV5GRGhYx4VxxI4dcs,170
10538
10544
  simo/users/templates/conf/mosquitto.conf,sha256=1eIGNuRu4Y3hfAU6qiWix648eCRrw0oOT24PnyFI4ys,189
10539
10545
  simo/users/templates/conf/mosquitto_acls.conf,sha256=ga44caTDNQE0CBKw55iM2jOuna6-9fKGwAhjyERZdRE,500
@@ -10543,9 +10549,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10543
10549
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10544
10550
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10545
10551
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10546
- simo-2.5.3.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10547
- simo-2.5.3.dist-info/METADATA,sha256=twUguJgwbaneN3x1oCPaSpfAtyfKV73LVKhxPl4NW8M,1923
10548
- simo-2.5.3.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
10549
- simo-2.5.3.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10550
- simo-2.5.3.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10551
- simo-2.5.3.dist-info/RECORD,,
10552
+ simo-2.5.4.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10553
+ simo-2.5.4.dist-info/METADATA,sha256=3NOTH7yR5Q9wTFLJjHqlmikVEEvUeoSlSB8XFcl-fMI,1923
10554
+ simo-2.5.4.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10555
+ simo-2.5.4.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10556
+ simo-2.5.4.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10557
+ simo-2.5.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
simo/scripting.py DELETED
@@ -1,39 +0,0 @@
1
- from django.utils import timezone
2
- from suntime import Sun
3
- from simo.core.middleware import get_current_instance
4
-
5
-
6
- class LocalSun(Sun):
7
-
8
- def __init__(self, instance=None):
9
- if not instance:
10
- instance = get_current_instance()
11
- coordinates = instance.location.split(',')
12
- try:
13
- lat = float(coordinates[0])
14
- except:
15
- lat = 0
16
- try:
17
- lon = float(coordinates[1])
18
- except:
19
- lon = 0
20
- super().__init__(lat, lon)
21
-
22
- def is_night(self):
23
- if timezone.now() > self.get_sunset_time():
24
- return True
25
- if timezone.now() < self.get_sunrise_time():
26
- return True
27
- return False
28
-
29
- def seconds_to_sunset(self):
30
- return (self.get_sunset_time() - timezone.now()).total_seconds()
31
-
32
- def seconds_to_sunrise(self):
33
- return (self.get_sunrise_time() - timezone.now()).total_seconds()
34
-
35
-
36
-
37
-
38
-
39
-