simo 2.5.30__py3-none-any.whl → 2.5.31__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__/models.cpython-38.pyc +0 -0
- simo/core/admin.py +12 -0
- simo/core/migrations/0045_alter_instance_device_report_history_days_and_more.py +36 -0
- simo/core/migrations/__pycache__/0045_alter_instance_device_report_history_days_and_more.cpython-38.pyc +0 -0
- simo/core/models.py +7 -4
- simo/users/__pycache__/admin.cpython-38.pyc +0 -0
- simo/users/__pycache__/api.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- simo/users/__pycache__/utils.cpython-38.pyc +0 -0
- simo/users/admin.py +10 -2
- simo/users/api.py +26 -22
- simo/users/migrations/0040_userdevicereportlog_location_smoothed_and_more.py +29 -0
- simo/users/migrations/__pycache__/0040_userdevicereportlog_location_smoothed_and_more.cpython-38.pyc +0 -0
- simo/users/models.py +2 -1
- simo/users/tasks.py +3 -1
- simo/users/utils.py +104 -1
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/METADATA +1 -1
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/RECORD +23 -19
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/LICENSE.md +0 -0
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/WHEEL +0 -0
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/entry_points.txt +0 -0
- {simo-2.5.30.dist-info → simo-2.5.31.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
simo/core/admin.py
CHANGED
|
@@ -60,6 +60,18 @@ class IconAdmin(EasyObjectsDeleteMixin, admin.ModelAdmin):
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
@admin.register(Instance)
|
|
64
|
+
class InstanceAdmin(admin.ModelAdmin):
|
|
65
|
+
list_display = 'name', 'slug', 'uid', 'timezone', 'is_active'
|
|
66
|
+
list_filter = 'is_active',
|
|
67
|
+
readonly_fields = 'uid',
|
|
68
|
+
|
|
69
|
+
def has_add_permission(self, request):
|
|
70
|
+
# instances are added via SIMO.io
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
63
75
|
@admin.register(Zone)
|
|
64
76
|
class ZoneAdmin(EasyObjectsDeleteMixin, SortableAdminMixin, admin.ModelAdmin):
|
|
65
77
|
list_display = 'name', 'instance'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-11-18 09:32
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django.db.models.deletion
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
12
|
+
('core', '0044_alter_gateway_type'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.AlterField(
|
|
17
|
+
model_name='instance',
|
|
18
|
+
name='device_report_history_days',
|
|
19
|
+
field=models.PositiveIntegerField(default=0, help_text='How many days of user device reports logs to keep? <br>Use 0 if you do not want to keep these logs at all.'),
|
|
20
|
+
),
|
|
21
|
+
migrations.AlterField(
|
|
22
|
+
model_name='instance',
|
|
23
|
+
name='history_days',
|
|
24
|
+
field=models.PositiveIntegerField(default=90, help_text='How many days of component history to keep?'),
|
|
25
|
+
),
|
|
26
|
+
migrations.AlterField(
|
|
27
|
+
model_name='instance',
|
|
28
|
+
name='learn_fingerprints',
|
|
29
|
+
field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
|
|
30
|
+
),
|
|
31
|
+
migrations.AlterField(
|
|
32
|
+
model_name='instance',
|
|
33
|
+
name='learn_fingerprints_start',
|
|
34
|
+
field=models.DateTimeField(blank=True, editable=False, null=True),
|
|
35
|
+
),
|
|
36
|
+
]
|
|
Binary file
|
simo/core/models.py
CHANGED
|
@@ -90,16 +90,19 @@ class Instance(DirtyFieldsMixin, models.Model, SimoAdminMixin):
|
|
|
90
90
|
limit_choices_to={'base_type__in': ['numeric-sensor', 'multi-sensor']}
|
|
91
91
|
)
|
|
92
92
|
history_days = models.PositiveIntegerField(
|
|
93
|
-
default=90, help_text="How many days of component history
|
|
93
|
+
default=90, help_text="How many days of component history to keep?"
|
|
94
94
|
)
|
|
95
95
|
device_report_history_days = models.PositiveIntegerField(
|
|
96
96
|
default=0,
|
|
97
|
-
help_text="How many days of user device reports
|
|
97
|
+
help_text="How many days of user device reports logs to keep? <br>"
|
|
98
98
|
"Use 0 if you do not want to keep these logs at all."
|
|
99
99
|
)
|
|
100
|
-
learn_fingerprints_start = models.DateTimeField(
|
|
100
|
+
learn_fingerprints_start = models.DateTimeField(
|
|
101
|
+
null=True, blank=True, editable=False
|
|
102
|
+
)
|
|
101
103
|
learn_fingerprints = models.ForeignKey(
|
|
102
|
-
User, null=True, blank=True, on_delete=models.SET_NULL
|
|
104
|
+
User, null=True, blank=True, on_delete=models.SET_NULL,
|
|
105
|
+
editable=False
|
|
103
106
|
)
|
|
104
107
|
|
|
105
108
|
#objects = InstanceManager()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/users/admin.py
CHANGED
|
@@ -4,6 +4,7 @@ from django.utils.safestring import mark_safe
|
|
|
4
4
|
from django.contrib import messages
|
|
5
5
|
from django.contrib.auth.admin import UserAdmin as OrgUserAdmin
|
|
6
6
|
from django.contrib import admin
|
|
7
|
+
from django.utils import timezone
|
|
7
8
|
from simo.core.middleware import get_current_instance
|
|
8
9
|
from .models import (
|
|
9
10
|
PermissionsRole, ComponentPermission, User, UserDevice, UserDeviceReportLog,
|
|
@@ -130,11 +131,13 @@ admin.site.unregister(Group)
|
|
|
130
131
|
class UserDeviceLog(admin.ModelAdmin):
|
|
131
132
|
model = UserDeviceReportLog
|
|
132
133
|
readonly_fields = (
|
|
133
|
-
'
|
|
134
|
+
'timestamp', 'app_open', 'relay', 'at_home',
|
|
135
|
+
'location', 'location_smoothed', 'users',
|
|
134
136
|
'speed_kmh', 'phone_on_charge'
|
|
135
137
|
)
|
|
136
138
|
list_display = (
|
|
137
|
-
'
|
|
139
|
+
'timestamp', 'app_open', 'relay', 'at_home',
|
|
140
|
+
'location', 'location_smoothed', 'speed_kmh',
|
|
138
141
|
'phone_on_charge', 'users'
|
|
139
142
|
)
|
|
140
143
|
fields = readonly_fields
|
|
@@ -143,6 +146,11 @@ class UserDeviceLog(admin.ModelAdmin):
|
|
|
143
146
|
def has_add_permission(self, request, obj=None):
|
|
144
147
|
return False
|
|
145
148
|
|
|
149
|
+
def timestamp(self, obj):
|
|
150
|
+
return obj.datetime.astimezone(
|
|
151
|
+
timezone.get_current_timezone()
|
|
152
|
+
).strftime("%m/%d/%Y, %H:%M:%S")
|
|
153
|
+
|
|
146
154
|
def users(self, obj):
|
|
147
155
|
return mark_safe(', '.join([
|
|
148
156
|
f'<a href="{user.get_admin_url()}">{user}</a>'
|
simo/users/api.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
import pytz
|
|
2
3
|
import datetime
|
|
3
4
|
from django.db.models import Q
|
|
4
5
|
from rest_framework import viewsets, mixins, status
|
|
@@ -6,11 +7,11 @@ from rest_framework.serializers import Serializer
|
|
|
6
7
|
from rest_framework.decorators import action
|
|
7
8
|
from rest_framework.response import Response as RESTResponse
|
|
8
9
|
from rest_framework.exceptions import ValidationError, PermissionDenied
|
|
9
|
-
from django.contrib.gis.geos import Point
|
|
10
10
|
from django.utils import timezone
|
|
11
11
|
from django_filters.rest_framework import DjangoFilterBackend
|
|
12
12
|
from simo.conf import dynamic_settings
|
|
13
13
|
from simo.core.api import InstanceMixin
|
|
14
|
+
from simo.users.utils import get_smoothed_location
|
|
14
15
|
from .models import (
|
|
15
16
|
User, UserDevice, UserDeviceReportLog, PermissionsRole, InstanceInvitation,
|
|
16
17
|
Fingerprint, ComponentPermission, InstanceUser
|
|
@@ -192,24 +193,22 @@ class UserDeviceReport(InstanceMixin, viewsets.GenericViewSet):
|
|
|
192
193
|
)
|
|
193
194
|
user_device.users.add(request.user)
|
|
194
195
|
|
|
195
|
-
try:
|
|
196
|
-
location = Point(
|
|
197
|
-
*[float(c) for c in request.data.get('location').split(',')],
|
|
198
|
-
srid=4326
|
|
199
|
-
)
|
|
200
|
-
except:
|
|
201
|
-
location = None
|
|
202
|
-
|
|
203
196
|
relay = None
|
|
204
197
|
if request.META.get('HTTP_HOST', '').endswith('.simo.io'):
|
|
205
198
|
relay = request.META.get('HTTP_HOST')
|
|
206
199
|
|
|
207
|
-
|
|
200
|
+
|
|
201
|
+
if relay:
|
|
202
|
+
location = request.data.get('location')
|
|
203
|
+
if location:
|
|
204
|
+
location_smoothed = get_smoothed_location(user_device, location)
|
|
205
|
+
else:
|
|
206
|
+
location_smoothed = None
|
|
207
|
+
else:
|
|
208
|
+
location = self.instance.location
|
|
209
|
+
location_smoothed = location
|
|
210
|
+
|
|
208
211
|
user_device.last_seen = timezone.now()
|
|
209
|
-
if location:
|
|
210
|
-
last_seen_location = ','.join(
|
|
211
|
-
[str(i) for i in location]
|
|
212
|
-
) if location else None
|
|
213
212
|
|
|
214
213
|
if request.data.get('app_open', False):
|
|
215
214
|
user_device.is_primary = True
|
|
@@ -226,31 +225,36 @@ class UserDeviceReport(InstanceMixin, viewsets.GenericViewSet):
|
|
|
226
225
|
at_home = False
|
|
227
226
|
if not relay:
|
|
228
227
|
at_home = True
|
|
229
|
-
elif
|
|
228
|
+
elif location_smoothed:
|
|
230
229
|
at_home = haversine_distance(
|
|
231
|
-
self.instance.location,
|
|
230
|
+
self.instance.location, location_smoothed
|
|
232
231
|
) < dynamic_settings['users__at_home_radius']
|
|
233
232
|
|
|
234
|
-
|
|
235
233
|
for iu in request.user.instance_roles.filter(is_active=True):
|
|
236
234
|
if not relay:
|
|
237
235
|
iu.at_home = True
|
|
238
|
-
elif
|
|
236
|
+
elif location_smoothed:
|
|
239
237
|
iu.at_home = haversine_distance(
|
|
240
|
-
iu.instance.location,
|
|
238
|
+
iu.instance.location, location_smoothed
|
|
241
239
|
) < dynamic_settings['users__at_home_radius']
|
|
242
240
|
|
|
243
|
-
|
|
244
241
|
iu.last_seen = user_device.last_seen
|
|
245
|
-
iu.last_seen_location =
|
|
242
|
+
iu.last_seen_location = location_smoothed
|
|
246
243
|
iu.last_seen_speed_kmh = speed_kmh
|
|
247
244
|
iu.phone_on_charge = phone_on_charge
|
|
248
245
|
iu.save()
|
|
249
246
|
|
|
247
|
+
log_datetime = timezone.now()
|
|
248
|
+
if request.data.get('timestamp'):
|
|
249
|
+
log_datetime = datetime.datetime.utcfromtimestamp(
|
|
250
|
+
int(float(request.GET['start_from']))
|
|
251
|
+
).replace(tzinfo=pytz.utc)
|
|
252
|
+
|
|
250
253
|
UserDeviceReportLog.objects.create(
|
|
251
254
|
user_device=user_device, instance=self.instance,
|
|
252
255
|
app_open=request.data.get('app_open', False),
|
|
253
|
-
location=
|
|
256
|
+
location=location, location_smoothed=location_smoothed,
|
|
257
|
+
datetime=log_datetime,
|
|
254
258
|
relay=relay, speed_kmh=speed_kmh,
|
|
255
259
|
phone_on_charge=phone_on_charge, at_home=at_home
|
|
256
260
|
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-11-18 09:32
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import location_field.models.plain
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('users', '0039_auto_20241117_1039'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='userdevicereportlog',
|
|
16
|
+
name='location_smoothed',
|
|
17
|
+
field=location_field.models.plain.PlainLocationField(blank=True, max_length=63, null=True),
|
|
18
|
+
),
|
|
19
|
+
migrations.AlterField(
|
|
20
|
+
model_name='userdevicereportlog',
|
|
21
|
+
name='at_home',
|
|
22
|
+
field=models.BooleanField(default=True),
|
|
23
|
+
),
|
|
24
|
+
migrations.AlterField(
|
|
25
|
+
model_name='userdevicereportlog',
|
|
26
|
+
name='datetime',
|
|
27
|
+
field=models.DateTimeField(auto_now_add=True, db_index=True),
|
|
28
|
+
),
|
|
29
|
+
]
|
simo/users/migrations/__pycache__/0040_userdevicereportlog_location_smoothed_and_more.cpython-38.pyc
ADDED
|
Binary file
|
simo/users/models.py
CHANGED
|
@@ -438,7 +438,7 @@ class UserDeviceReportLog(models.Model):
|
|
|
438
438
|
instance = models.ForeignKey(
|
|
439
439
|
'core.Instance', null=True, on_delete=models.CASCADE
|
|
440
440
|
)
|
|
441
|
-
datetime = models.DateTimeField(auto_now_add=True)
|
|
441
|
+
datetime = models.DateTimeField(auto_now_add=True, db_index=True)
|
|
442
442
|
app_open = models.BooleanField(
|
|
443
443
|
default=False, help_text="Sent while using app or by background process."
|
|
444
444
|
)
|
|
@@ -447,6 +447,7 @@ class UserDeviceReportLog(models.Model):
|
|
|
447
447
|
help_text="Sent via remote relay if specified, otherwise it's from LAN."
|
|
448
448
|
)
|
|
449
449
|
location = PlainLocationField(zoom=7, null=True, blank=True)
|
|
450
|
+
location_smoothed = PlainLocationField(zoom=7, null=True, blank=True)
|
|
450
451
|
speed_kmh = models.FloatField(default=0)
|
|
451
452
|
phone_on_charge = models.BooleanField(default=False, db_index=True)
|
|
452
453
|
at_home = models.BooleanField(default=True)
|
simo/users/tasks.py
CHANGED
|
@@ -8,10 +8,12 @@ def clear_device_report_logs():
|
|
|
8
8
|
from simo.core.models import Instance
|
|
9
9
|
from .models import UserDeviceReportLog
|
|
10
10
|
for instance in Instance.objects.all():
|
|
11
|
+
# keeping at least 1 hour of logs so that we could evaluate
|
|
12
|
+
# user's current location using Kalman filter
|
|
11
13
|
UserDeviceReportLog.objects.filter(
|
|
12
14
|
instance=instance,
|
|
13
15
|
datetime__lt=timezone.now() - datetime.timedelta(
|
|
14
|
-
days=instance.device_report_history_days
|
|
16
|
+
days=instance.device_report_history_days, hours=1
|
|
15
17
|
)
|
|
16
18
|
).delete()
|
|
17
19
|
|
simo/users/utils.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
import traceback
|
|
3
3
|
import subprocess
|
|
4
|
+
import datetime
|
|
5
|
+
import numpy as np
|
|
6
|
+
from django.core.cache import cache
|
|
7
|
+
from django.utils import timezone
|
|
4
8
|
from django.template.loader import render_to_string
|
|
5
9
|
|
|
6
10
|
|
|
@@ -58,4 +62,103 @@ def update_mqtt_acls():
|
|
|
58
62
|
)
|
|
59
63
|
subprocess.run(
|
|
60
64
|
['service', 'mosquitto', 'reload'], stdout=subprocess.PIPE
|
|
61
|
-
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class KalmanFilter:
|
|
69
|
+
def __init__(self, process_variance, measurement_variance, x=None, P=None):
|
|
70
|
+
self.x = x if x is not None else np.array([[0], [0], [0], [0]]) # State
|
|
71
|
+
self.P = P if P is not None else np.eye(4) # State covariance
|
|
72
|
+
self.process_variance = process_variance
|
|
73
|
+
self.measurement_variance = measurement_variance
|
|
74
|
+
|
|
75
|
+
def predict(self, delta_t):
|
|
76
|
+
F = np.array([
|
|
77
|
+
[1, 0, delta_t, 0],
|
|
78
|
+
[0, 1, 0, delta_t],
|
|
79
|
+
[0, 0, 1, 0],
|
|
80
|
+
[0, 0, 0, 1]
|
|
81
|
+
])
|
|
82
|
+
Q = self.process_variance * np.array([
|
|
83
|
+
[delta_t ** 4 / 4, 0, delta_t ** 3 / 2, 0],
|
|
84
|
+
[0, delta_t ** 4 / 4, 0, delta_t ** 3 / 2],
|
|
85
|
+
[delta_t ** 3 / 2, 0, delta_t ** 2, 0],
|
|
86
|
+
[0, delta_t ** 3 / 2, 0, delta_t ** 2]
|
|
87
|
+
])
|
|
88
|
+
self.x = np.dot(F, self.x)
|
|
89
|
+
self.P = np.dot(np.dot(F, self.P), F.T) + Q
|
|
90
|
+
|
|
91
|
+
def update(self, z):
|
|
92
|
+
H = np.array([
|
|
93
|
+
[1, 0, 0, 0],
|
|
94
|
+
[0, 1, 0, 0]
|
|
95
|
+
])
|
|
96
|
+
R = self.measurement_variance * np.eye(2)
|
|
97
|
+
y = z - np.dot(H, self.x) # Innovation
|
|
98
|
+
S = np.dot(H, np.dot(self.P, H.T)) + R # Innovation covariance
|
|
99
|
+
K = np.dot(np.dot(self.P, H.T), np.linalg.inv(S)) # Kalman Gain
|
|
100
|
+
self.x = self.x + np.dot(K, y)
|
|
101
|
+
I = np.eye(self.P.shape[0])
|
|
102
|
+
self.P = np.dot(I - np.dot(K, H), self.P)
|
|
103
|
+
|
|
104
|
+
def get_state(self):
|
|
105
|
+
return self.x[:2].flatten() # Latitude and Longitude
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_smoothed_location(user_device, new_location):
|
|
109
|
+
try:
|
|
110
|
+
new_lat, new_lon = map(float, new_location.split(','))
|
|
111
|
+
except ValueError:
|
|
112
|
+
raise ValueError("Invalid new location format. Expected 'lat,lon'.")
|
|
113
|
+
|
|
114
|
+
cache_key = f"kalman_state_{user_device.id}"
|
|
115
|
+
cached_data = cache.get(cache_key)
|
|
116
|
+
|
|
117
|
+
if cached_data:
|
|
118
|
+
kf = KalmanFilter(
|
|
119
|
+
process_variance=1,
|
|
120
|
+
measurement_variance=10,
|
|
121
|
+
x=np.array(cached_data['x']),
|
|
122
|
+
P=np.array(cached_data['P'])
|
|
123
|
+
)
|
|
124
|
+
last_processed_time = cached_data['last_processed_time']
|
|
125
|
+
else:
|
|
126
|
+
kf = KalmanFilter(process_variance=1, measurement_variance=10)
|
|
127
|
+
last_processed_time = None
|
|
128
|
+
|
|
129
|
+
last_log = None
|
|
130
|
+
logs_query = user_device.report_logs.filter(
|
|
131
|
+
location__isnull=False,
|
|
132
|
+
datetime__gt=last_processed_time or timezone.now() - datetime.timedelta(minutes=20)
|
|
133
|
+
).order_by('datetime')
|
|
134
|
+
|
|
135
|
+
for log in logs_query:
|
|
136
|
+
try:
|
|
137
|
+
lat, lon = map(float, log.location.split(','))
|
|
138
|
+
except ValueError:
|
|
139
|
+
continue # Skip invalid data
|
|
140
|
+
|
|
141
|
+
if last_log and log.location == last_log.location:
|
|
142
|
+
continue # Skip duplicate locations
|
|
143
|
+
|
|
144
|
+
if last_log:
|
|
145
|
+
delta_t = (log.datetime - last_log.datetime).total_seconds()
|
|
146
|
+
kf.predict(max(delta_t, 0)) # Prevent negative delta_t
|
|
147
|
+
|
|
148
|
+
kf.update(np.array([[lat], [lon]]))
|
|
149
|
+
last_log = log
|
|
150
|
+
|
|
151
|
+
if last_log:
|
|
152
|
+
delta_t = (timezone.now() - last_log.datetime).total_seconds()
|
|
153
|
+
kf.predict(max(delta_t, 0))
|
|
154
|
+
|
|
155
|
+
kf.update(np.array([[new_lat], [new_lon]]))
|
|
156
|
+
|
|
157
|
+
# Cache the updated filter state and last processed log time
|
|
158
|
+
cache.set(cache_key, {
|
|
159
|
+
'x': kf.x.tolist(), # Convert to list for JSON serialization
|
|
160
|
+
'P': kf.P.tolist(), # Convert to list for JSON serialization
|
|
161
|
+
'last_processed_time': timezone.now()
|
|
162
|
+
}, timeout=3600) # Cache for 1 hour
|
|
163
|
+
|
|
164
|
+
return ','.join(f"{coord:.6f}" for coord in kf.get_state())
|
|
@@ -32,7 +32,7 @@ simo/backups/migrations/__pycache__/0003_alter_backuplog_options_alter_backup_si
|
|
|
32
32
|
simo/backups/migrations/__pycache__/0004_alter_backup_options_alter_backuplog_options_and_more.cpython-38.pyc,sha256=f4leTBkOB2kraQYyCkz9B_2pb6aKn7srV2unQA5HV1Q,710
|
|
33
33
|
simo/backups/migrations/__pycache__/__init__.cpython-38.pyc,sha256=Lz1fs6V05h2AoxTOLNye0do9bEMnyuaXB_hHOjG5-HU,172
|
|
34
34
|
simo/core/__init__.py,sha256=_s2TjJfQImsMrTIxqLAx9AZie1Ojmm6sCHASdl3WLGU,50
|
|
35
|
-
simo/core/admin.py,sha256=
|
|
35
|
+
simo/core/admin.py,sha256=T-NjMq1OxtCt-LjWL-YuuGtAi4JcvtjWhcGrLb8G5D4,18434
|
|
36
36
|
simo/core/api.py,sha256=id8RCZ7r9IKqpcV6ajqF87k9yKqcFmSc8YfWIP99tQE,28276
|
|
37
37
|
simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
|
|
38
38
|
simo/core/api_meta.py,sha256=EaiY-dCADP__9MvLpoHvhjytFT92IrxPZDv95xgqasU,4955
|
|
@@ -52,7 +52,7 @@ simo/core/gateways.py,sha256=m0eS3XjVe34Dge6xtoCq16kFWCKJcdQrT0JW0REqoq8,3715
|
|
|
52
52
|
simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
|
|
53
53
|
simo/core/managers.py,sha256=n-b3I4uXzfHKTeB1VMjSaMsDUxp8FegFJwnbV1IsWQ4,3019
|
|
54
54
|
simo/core/middleware.py,sha256=eUFf6iP-Snx_0TE3MoXsSwqrd5IjlukqZk2GQGStRCo,3385
|
|
55
|
-
simo/core/models.py,sha256=
|
|
55
|
+
simo/core/models.py,sha256=1eJRIxOYtzx7JOGSAyo75QBoTEaigxjsRXIFghDSz9k,22837
|
|
56
56
|
simo/core/permissions.py,sha256=INQPrUAIM3WXCvd7e6cmYytKaak8fMEn7VooX-fIds0,3002
|
|
57
57
|
simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
|
|
58
58
|
simo/core/serializers.py,sha256=WgksN1Ombv240nfQR_UtmKslTWM9vz9Y0yTdN5usiHU,21892
|
|
@@ -65,7 +65,7 @@ simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
|
|
|
65
65
|
simo/core/views.py,sha256=3SRZr00fyLQf8ja3U-9eekKt-ld5TvU1WQqUWprXfQ4,2390
|
|
66
66
|
simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
|
|
67
67
|
simo/core/__pycache__/__init__.cpython-38.pyc,sha256=ZJFM_XN0RmJMULQulgA_wFiOnEtsMoedcOWnXjH-Y8o,208
|
|
68
|
-
simo/core/__pycache__/admin.cpython-38.pyc,sha256=
|
|
68
|
+
simo/core/__pycache__/admin.cpython-38.pyc,sha256=mXU-u9Bl5RCa0K4Y9wJAkYns33XCByME3sb_FsMC2DI,14090
|
|
69
69
|
simo/core/__pycache__/api.cpython-38.pyc,sha256=z5IT2AoH_Y7iXJELeGlgaxJ2RNe-Wwk8YIt_rJcOGMw,21851
|
|
70
70
|
simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=mi3mu5qEKio_PvfQEvr3Q6AhdPLAHxzxAxrMbAz_pKU,1712
|
|
71
71
|
simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=VYx5ZeDyNBI4B_CBEIhV5B3GnLsMOx9s3rNZTSMODco,3703
|
|
@@ -85,7 +85,7 @@ simo/core/__pycache__/gateways.cpython-38.pyc,sha256=D1ooHL-iSpQrxnD8uAl4xWFJmm-
|
|
|
85
85
|
simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
|
|
86
86
|
simo/core/__pycache__/managers.cpython-38.pyc,sha256=6RTIxyjOgpQGtAqcUyE2vFPS09w1V5Wmd_vOV7rHRRI,3370
|
|
87
87
|
simo/core/__pycache__/middleware.cpython-38.pyc,sha256=g3d4L2PwxFyRKIPMP9Hkdjk1PL9NarQd4hSHS55I8n8,2649
|
|
88
|
-
simo/core/__pycache__/models.cpython-38.pyc,sha256=
|
|
88
|
+
simo/core/__pycache__/models.cpython-38.pyc,sha256=m2KdO5zWXwHT3pIDyGW9SQgnesSAGPPcttOXoKCArzM,18610
|
|
89
89
|
simo/core/__pycache__/permissions.cpython-38.pyc,sha256=bO13B8uGCv4AiWNBoU2Gxt3mNuQ3gCxb7eKFihwFb5o,2974
|
|
90
90
|
simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
|
|
91
91
|
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=d4wpUjFuo8GxaNWbin9GdHKik06IZN32uZL1SnXiL_s,19616
|
|
@@ -207,6 +207,7 @@ simo/core/migrations/0041_alter_instance_slug.py,sha256=MmuW0n5CCpF7NyKYINDcqChO
|
|
|
207
207
|
simo/core/migrations/0042_alter_instance_timezone.py,sha256=5fLprOmoV06y37rh3uJWq8Fy4SjNmu86Imky6t7j13g,23334
|
|
208
208
|
simo/core/migrations/0043_alter_category_instance_alter_instance_timezone_and_more.py,sha256=TpJRZjwJu1iDYt1cCQr62jLOz14yy7yjrfbyHYgu9pM,23896
|
|
209
209
|
simo/core/migrations/0044_alter_gateway_type.py,sha256=xoQvOSz_JrWHECAAII83518tmhEEfLUHqxpIjoo4oLY,758
|
|
210
|
+
simo/core/migrations/0045_alter_instance_device_report_history_days_and_more.py,sha256=saR7gEbTDfXTcKnT1R193Aboqlg32HvDRI_JAvZ97TY,1360
|
|
210
211
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
211
212
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=w6GiBXVxWj30Bg4Sn_pFVeA041d-pCrkaq8mR3KuF70,5381
|
|
212
213
|
simo/core/migrations/__pycache__/0002_load_icons.cpython-38.pyc,sha256=Nb9RrPjVYo_RpZ5PmzoaEIWGCeVt4kicpmGiKlBrpIw,2123
|
|
@@ -252,6 +253,7 @@ simo/core/migrations/__pycache__/0041_alter_instance_slug.cpython-38.pyc,sha256=
|
|
|
252
253
|
simo/core/migrations/__pycache__/0042_alter_instance_timezone.cpython-38.pyc,sha256=_IdEOLCC0xgeVcKfCk7x0kKxVPu0iWuCxCg8aqkzeSI,16392
|
|
253
254
|
simo/core/migrations/__pycache__/0043_alter_category_instance_alter_instance_timezone_and_more.cpython-38.pyc,sha256=97_eFPQ_Iy-M1712Nad1w8t3ITBV4BF0eY1e8N-oOE4,16759
|
|
254
255
|
simo/core/migrations/__pycache__/0044_alter_gateway_type.cpython-38.pyc,sha256=KwqGKoo8C1wH9ZUhagpC3plTwheSMcWtwlCGcSPd5WQ,964
|
|
256
|
+
simo/core/migrations/__pycache__/0045_alter_instance_device_report_history_days_and_more.cpython-38.pyc,sha256=e1_hKjdokggnPndFkoBWrHQ18IkBi2W7WahcSjAbvKo,1278
|
|
255
257
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=VZmDQ57BTcebuM0KMhjiTOabgWZCBxQmSJzWZos9SO8,169
|
|
256
258
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
257
259
|
simo/core/static/admin/Img/plus.svg,sha256=2NpSFPWqGIjpAQGFI7LDQHPKagEhYkJiJX95ufCoZaI,741
|
|
@@ -10444,38 +10446,38 @@ simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-38.
|
|
|
10444
10446
|
simo/notifications/migrations/__pycache__/0003_alter_notification_instance.cpython-38.pyc,sha256=awhD1F9RyK_706zVNM5io3WT_konFkKQgL7D5MkONwk,851
|
|
10445
10447
|
simo/notifications/migrations/__pycache__/__init__.cpython-38.pyc,sha256=YMBRHVon2nWDtIUbghckjnC12sIg_ykPWhV5aM0tto4,178
|
|
10446
10448
|
simo/users/__init__.py,sha256=6a7uBpCWB_DR7p54rbHusc0xvi1qfT1ZCCQGb6TiBh8,52
|
|
10447
|
-
simo/users/admin.py,sha256=
|
|
10448
|
-
simo/users/api.py,sha256=
|
|
10449
|
+
simo/users/admin.py,sha256=SWKSb4giF69By3JYXuPMEd71Z_aCyin4_9NtIRJOY6I,7237
|
|
10450
|
+
simo/users/api.py,sha256=03QFEOnIlACetS4QsPPBdagsC15_ap0-I64lCnplitI,12651
|
|
10449
10451
|
simo/users/apps.py,sha256=cq0A8-U1HALEwev0TicgFhr4CAu7Icz8rwq0HfOaL4E,207
|
|
10450
10452
|
simo/users/auth_backends.py,sha256=KIw2AdjCUKfm_7Lql6aC4qdE6JznP0ECIMA5MVMLeiM,4251
|
|
10451
10453
|
simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
|
|
10452
10454
|
simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
|
|
10453
10455
|
simo/users/managers.py,sha256=OHgEP85MBtdkdYxdstBd8RavTBT8F_2WyDxUJ9aCqqM,246
|
|
10454
10456
|
simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
|
|
10455
|
-
simo/users/models.py,sha256=
|
|
10457
|
+
simo/users/models.py,sha256=2NAWk3n_bg7JLHh5y8_dl2-7VZ97HTvhu61kNZYdaJg,19760
|
|
10456
10458
|
simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
|
|
10457
10459
|
simo/users/serializers.py,sha256=zzw1KONTnaTNBaU0r4rNVxJ827KzD6Z5LuQt27ZsQ98,2516
|
|
10458
10460
|
simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
|
|
10459
10461
|
simo/users/sso_views.py,sha256=5J0D4qUFQDvd-Fcqx_xLJWLJgPdqtVD5DDiPJyPsT2Q,4336
|
|
10460
|
-
simo/users/tasks.py,sha256=
|
|
10461
|
-
simo/users/utils.py,sha256=
|
|
10462
|
+
simo/users/tasks.py,sha256=3oYo7xv6XIbrl9qY3JuCYJMncRDDXAmfoV59oYIHyXo,1110
|
|
10463
|
+
simo/users/utils.py,sha256=E9t6qljw3GARNMlH5qW7A_Ly1GaSNeAJcacxkQBJZyg,5457
|
|
10462
10464
|
simo/users/views.py,sha256=dOQVvmlHG7ihWKJLFUBcqKOA0UDctlMKR0pTc36JZqg,3487
|
|
10463
10465
|
simo/users/__pycache__/__init__.cpython-38.pyc,sha256=VFoDJE_SKKaPqqYaaBYd1Ndb1hjakkTo_u0EG_XJ1GM,211
|
|
10464
|
-
simo/users/__pycache__/admin.cpython-38.pyc,sha256
|
|
10465
|
-
simo/users/__pycache__/api.cpython-38.pyc,sha256=
|
|
10466
|
+
simo/users/__pycache__/admin.cpython-38.pyc,sha256=1HKy4UfOLaokGkk3s-eJgMEpa4snLEL7qA-b0vT3Rrc,8237
|
|
10467
|
+
simo/users/__pycache__/api.cpython-38.pyc,sha256=hO7qFF6oG-llh6Pm4y_3IU1KHgwWXBy_uqKdOKAK7Gc,10049
|
|
10466
10468
|
simo/users/__pycache__/apps.cpython-38.pyc,sha256=dgbWL8CxzzISJQTmq_4IztPJ2UzykNVdqA2Ae1PmeGk,605
|
|
10467
10469
|
simo/users/__pycache__/auth_backends.cpython-38.pyc,sha256=jYS2hlbTZh_ZtPeWcN50pc0IpyfCSO7_MvIbuVwEp8M,3144
|
|
10468
10470
|
simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=K-3sz2h-cEitoflSmZk1t0eUg5mQMMGLNZFREVwG7_o,430
|
|
10469
10471
|
simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
|
|
10470
10472
|
simo/users/__pycache__/managers.cpython-38.pyc,sha256=O0Y8ABp42RAosrbODmYsPMaj9AyOPyJ-aqzuO0Qpi2s,679
|
|
10471
10473
|
simo/users/__pycache__/middleware.cpython-38.pyc,sha256=Tj4nVEAvxEW3xA63fBRiJWRJpz_M848ZOqbHioc_IPE,1149
|
|
10472
|
-
simo/users/__pycache__/models.cpython-38.pyc,sha256=
|
|
10474
|
+
simo/users/__pycache__/models.cpython-38.pyc,sha256=fPZcTqgvuEokKa_TQyRA2eOZNwK_JYTvzTp1tyF3RwE,17716
|
|
10473
10475
|
simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
|
|
10474
10476
|
simo/users/__pycache__/serializers.cpython-38.pyc,sha256=Dy8RAcwNkNSXoJHvLp8fozURyHCtucqpSPyqZtbnMZc,3732
|
|
10475
10477
|
simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=uAwDozpOmrhUald-8tOHANILXkH7-TI8fNYXOtPkSY8,402
|
|
10476
10478
|
simo/users/__pycache__/sso_views.cpython-38.pyc,sha256=PLRF6FYCxRhnmgnN_gUS-pdQlH7lofLU1Xhgw3vDO_Y,4019
|
|
10477
10479
|
simo/users/__pycache__/tasks.cpython-38.pyc,sha256=XLMKt3suT7BlcXrJZoH9ZIhhtBuqyiW4lsOB9IbBkko,1225
|
|
10478
|
-
simo/users/__pycache__/utils.cpython-38.pyc,sha256=
|
|
10480
|
+
simo/users/__pycache__/utils.cpython-38.pyc,sha256=9qaNWqNX-5cFMJd9m6qtN-LyiLsVB97ea8y4E9Pr3DM,4701
|
|
10479
10481
|
simo/users/__pycache__/views.cpython-38.pyc,sha256=AXuUnVYRD0ai4FSFDp4qJwryukujAoN6LD3oIj-Cv3o,2426
|
|
10480
10482
|
simo/users/migrations/0001_initial.py,sha256=_SnJemhNOs8Jjj-PjyvTVCBoxfs5V3lR_4ypUHUdLUg,7017
|
|
10481
10483
|
simo/users/migrations/0002_componentpermission.py,sha256=rH9pC9HERf_5WWn3LCsNiu03BiHqURTF62pSNfswStI,918
|
|
@@ -10516,6 +10518,7 @@ simo/users/migrations/0036_instanceuser_phone_on_charge_user_phone_on_charge.py,
|
|
|
10516
10518
|
simo/users/migrations/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.py,sha256=8f_7fC7k0Dm-0gGVHMI9_490BbEC_SfuAPrAADrZ7BA,1543
|
|
10517
10519
|
simo/users/migrations/0038_userdevicereportlog_at_home_and_more.py,sha256=qL1ZjUJDiSrJat59ToqpNBwnMMPb3Q5mwHq-qd1eFcI,691
|
|
10518
10520
|
simo/users/migrations/0039_auto_20241117_1039.py,sha256=e64AJM2ZId516Px-gmAxkp2NmSC5Vjo_BBTGbYrFuKY,1310
|
|
10521
|
+
simo/users/migrations/0040_userdevicereportlog_location_smoothed_and_more.py,sha256=umGDjQGpCrQocNxaCvwdTsOmSxcRC61NcUdHGUczoc4,855
|
|
10519
10522
|
simo/users/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10520
10523
|
simo/users/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=e4XOKaYRb7l0P7cBnHHi5FQQJMlwjK0g7iqgM-xKmNI,4215
|
|
10521
10524
|
simo/users/migrations/__pycache__/0002_componentpermission.cpython-38.pyc,sha256=pknJnpic8p6Vdx9DX41FfODXNnvexDswJtUCmC5w1tg,995
|
|
@@ -10558,6 +10561,7 @@ simo/users/migrations/__pycache__/0036_instanceuser_phone_on_charge_user_phone_o
|
|
|
10558
10561
|
simo/users/migrations/__pycache__/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.cpython-38.pyc,sha256=W4Rc6SRNNJ_yAYrEyoklD5LFmQPAL9mTDrXHMfP8R4I,1162
|
|
10559
10562
|
simo/users/migrations/__pycache__/0038_userdevicereportlog_at_home_and_more.cpython-38.pyc,sha256=khDSeTH3-jJ4yO1D6-i3Pm_NekJkVwBSUJ-rAxu0cr4,836
|
|
10560
10563
|
simo/users/migrations/__pycache__/0039_auto_20241117_1039.cpython-38.pyc,sha256=IEOIfvnUiV-GX9VI4W2UKJugC3nfwKfy7QdmS3pW6Ss,1377
|
|
10564
|
+
simo/users/migrations/__pycache__/0040_userdevicereportlog_location_smoothed_and_more.cpython-38.pyc,sha256=I0W00mt73gjKunnwAyf3kz1FKfgm2HRwCJY_ogATSS0,918
|
|
10561
10565
|
simo/users/migrations/__pycache__/__init__.cpython-38.pyc,sha256=NKq7WLgktK8WV1oOqCPbAbdkrPV5GRGhYx4VxxI4dcs,170
|
|
10562
10566
|
simo/users/templates/conf/mosquitto.conf,sha256=1eIGNuRu4Y3hfAU6qiWix648eCRrw0oOT24PnyFI4ys,189
|
|
10563
10567
|
simo/users/templates/conf/mosquitto_acls.conf,sha256=ga44caTDNQE0CBKw55iM2jOuna6-9fKGwAhjyERZdRE,500
|
|
@@ -10567,9 +10571,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10567
10571
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10568
10572
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10569
10573
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10570
|
-
simo-2.5.
|
|
10571
|
-
simo-2.5.
|
|
10572
|
-
simo-2.5.
|
|
10573
|
-
simo-2.5.
|
|
10574
|
-
simo-2.5.
|
|
10575
|
-
simo-2.5.
|
|
10574
|
+
simo-2.5.31.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10575
|
+
simo-2.5.31.dist-info/METADATA,sha256=nFDDYX4oUK_5gtNMScQSzfboiiS7didaCErf8noKlDM,1953
|
|
10576
|
+
simo-2.5.31.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
10577
|
+
simo-2.5.31.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
|
|
10578
|
+
simo-2.5.31.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10579
|
+
simo-2.5.31.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|