simo 2.7.10__py3-none-any.whl → 2.7.11__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/automation/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/automation/__pycache__/helpers.cpython-38.pyc +0 -0
- simo/automation/__pycache__/models.cpython-38.pyc +0 -0
- simo/automation/__pycache__/serializers.cpython-38.pyc +0 -0
- simo/automation/gateways.py +45 -25
- simo/core/__pycache__/admin.cpython-38.pyc +0 -0
- simo/core/__pycache__/api_meta.cpython-38.pyc +0 -0
- simo/core/__pycache__/form_fields.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/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/core/api_meta.py +3 -1
- simo/core/form_fields.py +7 -1
- simo/core/forms.py +6 -3
- simo/core/migrations/0047_alter_component_value_translation.py +18 -0
- simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-38.pyc +0 -0
- simo/core/serializers.py +6 -1
- simo/core/templates/admin/wizard/wizard_add.html +1 -1
- simo/fleet/__pycache__/forms.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/fleet/__pycache__/views.cpython-38.pyc +0 -0
- simo/fleet/migrations/__pycache__/0044_auto_20241210_0707.cpython-38.pyc +0 -0
- simo/generic/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/generic/__pycache__/forms.cpython-38.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-38.pyc +0 -0
- simo/generic/__pycache__/socket_consumers.cpython-38.pyc +0 -0
- simo/generic/controllers.py +10 -1
- simo/generic/forms.py +36 -0
- simo/generic/gateways.py +45 -3
- simo/multimedia/__pycache__/admin.cpython-38.pyc +0 -0
- simo/multimedia/__pycache__/auto_urls.cpython-38.pyc +0 -0
- simo/multimedia/__pycache__/controllers.cpython-38.pyc +0 -0
- simo/multimedia/__pycache__/models.cpython-38.pyc +0 -0
- simo/multimedia/__pycache__/views.cpython-38.pyc +0 -0
- simo/multimedia/admin.py +4 -4
- simo/multimedia/auto_urls.py +10 -0
- simo/multimedia/controllers.py +9 -1
- simo/multimedia/migrations/0005_remove_sound_slug_sound_date_uploaded.py +24 -0
- simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-38.pyc +0 -0
- simo/multimedia/models.py +16 -2
- simo/multimedia/views.py +19 -0
- simo/notifications/__pycache__/utils.cpython-38.pyc +0 -0
- simo/users/__pycache__/models.cpython-38.pyc +0 -0
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/METADATA +1 -1
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/RECORD +50 -42
- simo/multimedia/requirements.txt +0 -2
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/LICENSE.md +0 -0
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/WHEEL +0 -0
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/entry_points.txt +0 -0
- {simo-2.7.10.dist-info → simo-2.7.11.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/automation/gateways.py
CHANGED
|
@@ -33,9 +33,12 @@ class ScriptRunHandler(multiprocessing.Process):
|
|
|
33
33
|
component = None
|
|
34
34
|
logger = None
|
|
35
35
|
|
|
36
|
-
def __init__(self, component_id, *args, **kwargs):
|
|
36
|
+
def __init__(self, component_id, exit_event, *args, **kwargs):
|
|
37
37
|
super().__init__(*args, **kwargs)
|
|
38
38
|
self.component_id = component_id
|
|
39
|
+
self.exit_event = exit_event
|
|
40
|
+
self.exit_in_use = multiprocessing.Event()
|
|
41
|
+
self.exin_in_use_fail = multiprocessing.Event()
|
|
39
42
|
|
|
40
43
|
def run(self):
|
|
41
44
|
db_connection.connect()
|
|
@@ -51,34 +54,40 @@ class ScriptRunHandler(multiprocessing.Process):
|
|
|
51
54
|
sys.stderr = StreamToLogger(self.logger, logging.ERROR)
|
|
52
55
|
self.component.meta['pid'] = os.getpid()
|
|
53
56
|
self.component.set('running')
|
|
54
|
-
|
|
55
|
-
if hasattr(self.component.controller, '_run'):
|
|
56
|
-
def run_code():
|
|
57
|
-
self.component.controller._run()
|
|
58
|
-
else:
|
|
59
|
-
code = self.component.config.get('code')
|
|
60
|
-
def run_code():
|
|
61
|
-
start = time.time()
|
|
62
|
-
exec(code, globals())
|
|
63
|
-
if 'class Automation:' in code and time.time() - start < 1:
|
|
64
|
-
Automation().run()
|
|
65
|
-
|
|
66
|
-
if not code:
|
|
67
|
-
self.component.value = 'finished'
|
|
68
|
-
self.component.save(update_fields=['value'])
|
|
69
|
-
return
|
|
70
57
|
print("------START-------")
|
|
71
58
|
try:
|
|
72
|
-
run_code()
|
|
59
|
+
self.run_code()
|
|
73
60
|
except:
|
|
74
61
|
print("------ERROR------")
|
|
75
62
|
self.component.set('error')
|
|
76
63
|
raise
|
|
77
64
|
else:
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
if not self.exit_event.is_set():
|
|
66
|
+
print("------FINISH-----")
|
|
67
|
+
self.component.set('finished')
|
|
80
68
|
return
|
|
81
69
|
|
|
70
|
+
def run_code(self):
|
|
71
|
+
if hasattr(self.component.controller, '_run'):
|
|
72
|
+
self.component.controller._run()
|
|
73
|
+
else:
|
|
74
|
+
code = self.component.config.get('code')
|
|
75
|
+
if not code:
|
|
76
|
+
self.component.value = 'finished'
|
|
77
|
+
self.component.save(update_fields=['value'])
|
|
78
|
+
return
|
|
79
|
+
start = time.time()
|
|
80
|
+
namespace = {}
|
|
81
|
+
exec(code, namespace)
|
|
82
|
+
if 'Automation' in namespace and time.time() - start < 1:
|
|
83
|
+
self.exit_in_use.set()
|
|
84
|
+
try:
|
|
85
|
+
namespace['Automation']().run(self.exit_event)
|
|
86
|
+
except:
|
|
87
|
+
self.exin_in_use_fail.set()
|
|
88
|
+
namespace['Automation']().run()
|
|
89
|
+
|
|
90
|
+
|
|
82
91
|
|
|
83
92
|
class GatesHandler:
|
|
84
93
|
'''
|
|
@@ -225,6 +234,9 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
225
234
|
dead_scripts = False
|
|
226
235
|
for id, process in list(self.running_scripts.items()):
|
|
227
236
|
comp = Component.objects.filter(id=id).first()
|
|
237
|
+
if comp.value == 'finished':
|
|
238
|
+
self.running_scripts.pop(id)
|
|
239
|
+
continue
|
|
228
240
|
if process.is_alive():
|
|
229
241
|
if not comp and id not in self.terminating_scripts:
|
|
230
242
|
# script is deleted, or instance deactivated
|
|
@@ -236,7 +248,7 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
236
248
|
if comp:
|
|
237
249
|
logger = get_component_logger(comp)
|
|
238
250
|
logger.log(logging.INFO, "-------DEAD!-------")
|
|
239
|
-
self.stop_script(comp, '
|
|
251
|
+
self.stop_script(comp, 'dead')
|
|
240
252
|
|
|
241
253
|
if dead_scripts:
|
|
242
254
|
# give 10s air before we wake these dead scripts up!
|
|
@@ -326,7 +338,9 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
326
338
|
def start_script(self, component):
|
|
327
339
|
print("START SCRIPT %s" % str(component))
|
|
328
340
|
if component.id in self.running_scripts:
|
|
329
|
-
if component.
|
|
341
|
+
if component.value == 'finished':
|
|
342
|
+
self.running_scripts.pop(component.id)
|
|
343
|
+
elif component.id not in self.terminating_scripts:
|
|
330
344
|
if component.value != 'running':
|
|
331
345
|
component.value = 'running'
|
|
332
346
|
component.save()
|
|
@@ -343,7 +357,8 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
343
357
|
return self.stop_script(component, 'error')
|
|
344
358
|
|
|
345
359
|
self.running_scripts[component.id] = ScriptRunHandler(
|
|
346
|
-
component.id,
|
|
360
|
+
component.id, multiprocessing.Event(),
|
|
361
|
+
daemon=True
|
|
347
362
|
)
|
|
348
363
|
self.running_scripts[component.id].start()
|
|
349
364
|
|
|
@@ -360,9 +375,14 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
360
375
|
logger = get_component_logger(component)
|
|
361
376
|
if stop_status == 'error':
|
|
362
377
|
logger.log(logging.INFO, "-------GATEWAY STOP-------")
|
|
363
|
-
|
|
378
|
+
elif stop_status == 'stopped':
|
|
364
379
|
logger.log(logging.INFO, "-------STOP-------")
|
|
365
|
-
|
|
380
|
+
|
|
381
|
+
if self.running_scripts[component.id].exit_in_use.is_set()\
|
|
382
|
+
and not self.running_scripts[component.id].exin_in_use_fail.is_set():
|
|
383
|
+
self.running_scripts[component.id].exit_event.set()
|
|
384
|
+
else:
|
|
385
|
+
self.running_scripts[component.id].terminate()
|
|
366
386
|
|
|
367
387
|
def kill():
|
|
368
388
|
start = time.time()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/core/api_meta.py
CHANGED
|
@@ -8,7 +8,8 @@ from simo.core.models import Icon, Instance, Category, Zone
|
|
|
8
8
|
from simo.core.middleware import introduce_instance
|
|
9
9
|
from .serializers import (
|
|
10
10
|
HiddenSerializerField, ComponentManyToManyRelatedField,
|
|
11
|
-
TextAreaSerializerField, Component, LocationSerializer
|
|
11
|
+
TextAreaSerializerField, Component, LocationSerializer,
|
|
12
|
+
SoundSerializer
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
|
|
@@ -33,6 +34,7 @@ class SIMOAPIMetadata(SimpleMetadata):
|
|
|
33
34
|
serializers.MultipleChoiceField: 'multiple choice',
|
|
34
35
|
serializers.FileField: 'file upload',
|
|
35
36
|
serializers.ImageField: 'image upload',
|
|
37
|
+
SoundSerializer: 'sound upload',
|
|
36
38
|
serializers.ListField: 'list',
|
|
37
39
|
serializers.DictField: 'nested object',
|
|
38
40
|
serializers.Serializer: 'nested object',
|
simo/core/form_fields.py
CHANGED
|
@@ -182,4 +182,10 @@ class PlainLocationField(forms.fields.CharField):
|
|
|
182
182
|
if attr in kwargs:
|
|
183
183
|
dwargs[attr] = kwargs[attr]
|
|
184
184
|
|
|
185
|
-
super(PlainLocationField, self).__init__(*args, **dwargs)
|
|
185
|
+
super(PlainLocationField, self).__init__(*args, **dwargs)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class SoundField(forms.fields.FileField):
|
|
190
|
+
pass
|
|
191
|
+
|
simo/core/forms.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import traceback
|
|
1
|
+
import traceback, json
|
|
2
2
|
from dal import forward
|
|
3
3
|
from django.contrib.admin.forms import AdminAuthenticationForm as OrgAdminAuthenticationForm
|
|
4
4
|
from django.db import models
|
|
@@ -117,8 +117,11 @@ class ConfigFieldsMixin:
|
|
|
117
117
|
obj.pk for obj in self.cleaned_data[field_name]
|
|
118
118
|
]
|
|
119
119
|
else:
|
|
120
|
-
|
|
121
|
-
self.
|
|
120
|
+
try:
|
|
121
|
+
self.instance.config[field_name] = \
|
|
122
|
+
json.loads(json.dumps(self.cleaned_data[field_name]))
|
|
123
|
+
except:
|
|
124
|
+
continue
|
|
122
125
|
|
|
123
126
|
if commit:
|
|
124
127
|
from simo.users.middleware import get_current_user
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-12-11 14:14
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('core', '0046_component_value_translation_alter_gateway_type'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='component',
|
|
15
|
+
name='value_translation',
|
|
16
|
+
field=models.TextField(blank=True, default="def translate(value, occasion):\n if occasion == 'before-set':\n return value\n else: # 'before-send'\n return value", help_text='Adjust this to make value translations before value isset on to a component and before it is sent to a device from your SIMO.io smart home instance.'),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
Binary file
|
simo/core/serializers.py
CHANGED
|
@@ -16,7 +16,7 @@ from simo.core.forms import HiddenField, FormsetField
|
|
|
16
16
|
from simo.core.form_fields import (
|
|
17
17
|
Select2ListChoiceField, Select2ModelChoiceField,
|
|
18
18
|
Select2ListMultipleChoiceField, Select2ModelMultipleChoiceField,
|
|
19
|
-
PlainLocationField
|
|
19
|
+
PlainLocationField, SoundField
|
|
20
20
|
)
|
|
21
21
|
from simo.core.models import Component
|
|
22
22
|
from rest_framework.relations import PrimaryKeyRelatedField, ManyRelatedField
|
|
@@ -33,6 +33,10 @@ class LocationSerializer(serializers.CharField):
|
|
|
33
33
|
pass
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
class SoundSerializer(serializers.FileField):
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
|
|
37
41
|
class TimestampField(serializers.Field):
|
|
38
42
|
|
|
@@ -145,6 +149,7 @@ class ComponentFormsetField(FormSerializer):
|
|
|
145
149
|
field_mapping = {
|
|
146
150
|
HiddenField: HiddenSerializerField,
|
|
147
151
|
PlainLocationField: LocationSerializer,
|
|
152
|
+
SoundField: SoundSerializer,
|
|
148
153
|
Select2ListChoiceField: serializers.ChoiceField,
|
|
149
154
|
forms.ModelChoiceField: FormsetPrimaryKeyRelatedField,
|
|
150
155
|
Select2ModelChoiceField: FormsetPrimaryKeyRelatedField,
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
</ul>
|
|
34
34
|
{% endif %}{% endif %}
|
|
35
35
|
{% endblock %}
|
|
36
|
-
<form
|
|
36
|
+
<form enctype="multipart/form-data" action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
|
37
37
|
<div>
|
|
38
38
|
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
|
|
39
39
|
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/generic/controllers.py
CHANGED
|
@@ -37,7 +37,7 @@ from .forms import (
|
|
|
37
37
|
ThermostatConfigForm, AlarmGroupConfigForm,
|
|
38
38
|
IPCameraConfigForm, WeatherForm,
|
|
39
39
|
WateringConfigForm, StateSelectForm, MainStateSelectForm,
|
|
40
|
-
AlarmClockConfigForm
|
|
40
|
+
AlarmClockConfigForm, AudioAlertConfigForm
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
# ----------- Generic controllers -----------------------------
|
|
@@ -1054,6 +1054,12 @@ class AlarmClock(ControllerBase):
|
|
|
1054
1054
|
return current_value
|
|
1055
1055
|
|
|
1056
1056
|
|
|
1057
|
+
class AudioAlert(Switch):
|
|
1058
|
+
gateway_class = GenericGatewayHandler
|
|
1059
|
+
name = _("Audio Alert")
|
|
1060
|
+
config_form = AudioAlertConfigForm
|
|
1061
|
+
|
|
1062
|
+
|
|
1057
1063
|
class StateSelect(ControllerBase):
|
|
1058
1064
|
gateway_class = GenericGatewayHandler
|
|
1059
1065
|
name = _("State select")
|
|
@@ -1188,6 +1194,9 @@ class MainState(StateSelect):
|
|
|
1188
1194
|
return any(phones_on_charge)
|
|
1189
1195
|
|
|
1190
1196
|
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1191
1200
|
# ----------- Dummy controllers -----------------------------
|
|
1192
1201
|
|
|
1193
1202
|
class DummyBinarySensor(BinarySensor):
|
simo/generic/forms.py
CHANGED
|
@@ -17,6 +17,8 @@ from simo.core.form_fields import (
|
|
|
17
17
|
Select2ModelMultipleChoiceField
|
|
18
18
|
)
|
|
19
19
|
from simo.core.forms import DimmerConfigForm, SwitchForm
|
|
20
|
+
from simo.core.form_fields import SoundField
|
|
21
|
+
from simo.multimedia.models import Sound
|
|
20
22
|
|
|
21
23
|
ACTION_METHODS = (
|
|
22
24
|
('turn_on', "Turn ON"), ('turn_off', "Turn OFF"),
|
|
@@ -613,3 +615,37 @@ class AlarmClockConfigForm(BaseComponentForm):
|
|
|
613
615
|
if c:
|
|
614
616
|
obj.slaves.add(c)
|
|
615
617
|
return obj
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
class AudioAlertConfigForm(BaseComponentForm):
|
|
621
|
+
sound = SoundField()
|
|
622
|
+
loop = forms.BooleanField(initial=False, required=False)
|
|
623
|
+
volume = forms.IntegerField(initial=30, min_value=2, max_value=100)
|
|
624
|
+
players = Select2ModelMultipleChoiceField(
|
|
625
|
+
queryset=Component.objects.all(),#filter(base_type='audio-player'),
|
|
626
|
+
url='autocomplete-component',
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
def __init__(self, *args, **kwargs):
|
|
630
|
+
super().__init__(*args, **kwargs)
|
|
631
|
+
self.basic_fields.extend(['sound', 'loop', 'volume', 'players'])
|
|
632
|
+
if self.instance.id:
|
|
633
|
+
sound = Sound.objects.filter(
|
|
634
|
+
id=self.instance.config.get('sound_id', 0)
|
|
635
|
+
).first()
|
|
636
|
+
if sound:
|
|
637
|
+
self.fields['sound'].initial = sound.file
|
|
638
|
+
|
|
639
|
+
def save(self, commit=True):
|
|
640
|
+
if commit and self.cleaned_data['sound'] \
|
|
641
|
+
and self.cleaned_data['sound'] != self.fields['sound'].initial:
|
|
642
|
+
sound = Sound(
|
|
643
|
+
name=self.cleaned_data['sound'].name,
|
|
644
|
+
)
|
|
645
|
+
sound.file.save(
|
|
646
|
+
self.cleaned_data['sound'].name, self.cleaned_data['sound'],
|
|
647
|
+
save=True
|
|
648
|
+
)
|
|
649
|
+
self.instance.config['sound_id'] = sound.id
|
|
650
|
+
self.cleaned_data.pop('sound')
|
|
651
|
+
return super().save(commit=commit)
|
simo/generic/gateways.py
CHANGED
|
@@ -134,8 +134,47 @@ class GroupButtonsHandler:
|
|
|
134
134
|
group.toggle()
|
|
135
135
|
|
|
136
136
|
|
|
137
|
+
class AudioAlertsHandler:
|
|
138
|
+
|
|
139
|
+
def control_audio_alert(self, component, val):
|
|
140
|
+
if val:
|
|
141
|
+
from simo.multimedia.models import Sound
|
|
142
|
+
sound = Sound.objects.filter(
|
|
143
|
+
id=component.config.get('sound_id')
|
|
144
|
+
).first()
|
|
145
|
+
if not sound:
|
|
146
|
+
return
|
|
147
|
+
loop = component.config.get('loop', False)
|
|
148
|
+
for pl_id in component.config.get('players', []):
|
|
149
|
+
player = Component.objects.filter(
|
|
150
|
+
id=pl_id, base_type='audio-player'
|
|
151
|
+
).first()
|
|
152
|
+
if not player:
|
|
153
|
+
continue
|
|
154
|
+
player.play_alert(
|
|
155
|
+
sound.id,
|
|
156
|
+
component.config.get('loop', False),
|
|
157
|
+
component.config.get('volume', 50)
|
|
158
|
+
)
|
|
159
|
+
if not loop:
|
|
160
|
+
def set_done(comp):
|
|
161
|
+
comp.set(False)
|
|
162
|
+
threading.Timer(sound.length, set_done, args=[component])
|
|
163
|
+
component.set(True)
|
|
164
|
+
else:
|
|
165
|
+
for pl_id in component.config.get('players', []):
|
|
166
|
+
player = Component.objects.filter(
|
|
167
|
+
id=pl_id, base_type='audio-player'
|
|
168
|
+
).first()
|
|
169
|
+
if not player:
|
|
170
|
+
continue
|
|
171
|
+
player.cancel_alert()
|
|
172
|
+
component.set(False)
|
|
173
|
+
|
|
137
174
|
|
|
138
|
-
class GenericGatewayHandler(
|
|
175
|
+
class GenericGatewayHandler(
|
|
176
|
+
BaseObjectCommandsGatewayHandler, GroupButtonsHandler, AudioAlertsHandler
|
|
177
|
+
):
|
|
139
178
|
name = "Generic"
|
|
140
179
|
config_form = BaseGatewayForm
|
|
141
180
|
info = "Provides generic type components which use other components to operate like " \
|
|
@@ -149,7 +188,8 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
149
188
|
('watch_watering', 60),
|
|
150
189
|
('watch_alarm_events', 1),
|
|
151
190
|
('watch_timers', 1),
|
|
152
|
-
('watch_main_states', 60)
|
|
191
|
+
('watch_main_states', 60),
|
|
192
|
+
('watch_groups', 60)
|
|
153
193
|
)
|
|
154
194
|
|
|
155
195
|
def __init__(self, *args, **kwargs):
|
|
@@ -229,7 +269,7 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
229
269
|
|
|
230
270
|
def on_mqtt_message(self, client, userdata, msg):
|
|
231
271
|
print("Mqtt message: ", msg.payload)
|
|
232
|
-
from simo.generic.controllers import AlarmGroup
|
|
272
|
+
from simo.generic.controllers import AlarmGroup, AudioAlert
|
|
233
273
|
|
|
234
274
|
payload = json.loads(msg.payload)
|
|
235
275
|
drop_current_instance()
|
|
@@ -239,6 +279,8 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
|
|
|
239
279
|
try:
|
|
240
280
|
if component.controller_uid == AlarmGroup.uid:
|
|
241
281
|
self.control_alarm_group(component, payload.get('set_val'))
|
|
282
|
+
elif component.controller_uid == AudioAlert.uid:
|
|
283
|
+
self.control_audio_alert(component, payload.get('set_val'))
|
|
242
284
|
else:
|
|
243
285
|
component.controller.set(payload.get('set_val'))
|
|
244
286
|
except Exception:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
simo/multimedia/admin.py
CHANGED
|
@@ -7,10 +7,9 @@ from .forms import SoundModelForm
|
|
|
7
7
|
|
|
8
8
|
@admin.register(Sound)
|
|
9
9
|
class SoundAdmin(admin.ModelAdmin):
|
|
10
|
-
list_display = 'id', 'name', '
|
|
11
|
-
search_fields = 'name', '
|
|
12
|
-
|
|
13
|
-
list_display_links = 'id', 'name', 'slug'
|
|
10
|
+
list_display = 'id', 'name', 'file', 'length_display', 'date_uploaded'
|
|
11
|
+
search_fields = 'name', 'file'
|
|
12
|
+
list_display_links = 'id', 'name',
|
|
14
13
|
form = SoundModelForm
|
|
15
14
|
readonly_fields = 'length_display',
|
|
16
15
|
|
|
@@ -22,6 +21,7 @@ class SoundAdmin(admin.ModelAdmin):
|
|
|
22
21
|
|
|
23
22
|
def save_model(self, request, obj, form, change):
|
|
24
23
|
super().save_model(request, obj, form, change)
|
|
24
|
+
# need to keep it here as using admin interface skips post_save signals
|
|
25
25
|
try:
|
|
26
26
|
obj.length = int(
|
|
27
27
|
librosa.core.get_duration(
|
simo/multimedia/controllers.py
CHANGED
|
@@ -89,10 +89,11 @@ class BasePlayer(Switch):
|
|
|
89
89
|
assert 0 <= volume <= 100
|
|
90
90
|
self.send({"play_uri": uri, 'volume': volume})
|
|
91
91
|
|
|
92
|
-
def play_alert(self, val, volume=None):
|
|
92
|
+
def play_alert(self, val, loop=False, volume=None):
|
|
93
93
|
'''
|
|
94
94
|
Plays alert and goes back to whatever was playing initially
|
|
95
95
|
:param val: Sound.id or uri
|
|
96
|
+
:param loop: Repeat infinitely
|
|
96
97
|
:param volume: volume at which to play
|
|
97
98
|
:return:
|
|
98
99
|
'''
|
|
@@ -101,6 +102,10 @@ class BasePlayer(Switch):
|
|
|
101
102
|
assert 0 <= volume <= 100
|
|
102
103
|
self.send({"alert": val, 'volume': volume})
|
|
103
104
|
|
|
105
|
+
def cancel_alert(self):
|
|
106
|
+
'''Cancel alert if it's currently playing'''
|
|
107
|
+
self.send({"alert": None})
|
|
108
|
+
|
|
104
109
|
def toggle(self):
|
|
105
110
|
if self.component.value == 'playing':
|
|
106
111
|
self.pause()
|
|
@@ -120,3 +125,6 @@ class BaseVideoPlayer(BasePlayer):
|
|
|
120
125
|
name = _("Video Player")
|
|
121
126
|
base_type = 'video-player'
|
|
122
127
|
app_widget = VideoPlayerWidget
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2024-12-11 14:14
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.utils.timezone
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('multimedia', '0004_auto_20231023_1055'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.RemoveField(
|
|
15
|
+
model_name='sound',
|
|
16
|
+
name='slug',
|
|
17
|
+
),
|
|
18
|
+
migrations.AddField(
|
|
19
|
+
model_name='sound',
|
|
20
|
+
name='date_uploaded',
|
|
21
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
22
|
+
preserve_default=False,
|
|
23
|
+
),
|
|
24
|
+
]
|
simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-38.pyc
ADDED
|
Binary file
|
simo/multimedia/models.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import os
|
|
1
|
+
import os, librosa
|
|
2
2
|
from django.db import models
|
|
3
|
+
from django.db.models.signals import post_save, post_delete
|
|
4
|
+
from django.dispatch import receiver
|
|
3
5
|
from django.core.files.storage import FileSystemStorage
|
|
4
6
|
from django.conf import settings
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class Sound(models.Model):
|
|
8
10
|
name = models.CharField(max_length=100, db_index=True)
|
|
9
|
-
slug = models.SlugField()
|
|
10
11
|
file = models.FileField(
|
|
11
12
|
upload_to='sounds', storage=FileSystemStorage(
|
|
12
13
|
location=os.path.join(settings.VAR_DIR, 'public_media'),
|
|
@@ -17,9 +18,22 @@ class Sound(models.Model):
|
|
|
17
18
|
length = models.PositiveIntegerField(
|
|
18
19
|
editable=False, default=0, help_text='Sound length in seconds'
|
|
19
20
|
)
|
|
21
|
+
date_uploaded = models.DateTimeField(auto_now_add=True)
|
|
20
22
|
|
|
21
23
|
def __str__(self):
|
|
22
24
|
return self.name
|
|
23
25
|
|
|
24
26
|
def get_absolute_url(self):
|
|
25
27
|
return self.file.url
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@receiver(post_save, sender=Sound)
|
|
31
|
+
def determine_duration(sender, instance, created, **kwargs):
|
|
32
|
+
if not instance.length:
|
|
33
|
+
instance.length = int(
|
|
34
|
+
librosa.core.get_duration(
|
|
35
|
+
sr=22050, filename=instance.file.path
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
instance.save()
|
|
39
|
+
|
simo/multimedia/views.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from django.http import Http404
|
|
2
|
+
from dal import autocomplete
|
|
3
|
+
from simo.core.utils.helpers import search_queryset
|
|
4
|
+
from .models import Sound
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SoundAutocomplete(autocomplete.Select2QuerySetView):
|
|
8
|
+
|
|
9
|
+
def get_queryset(self):
|
|
10
|
+
if not self.request.user.is_authenticated:
|
|
11
|
+
raise Http404()
|
|
12
|
+
|
|
13
|
+
qs = Sound.objects.all()
|
|
14
|
+
|
|
15
|
+
if self.request.GET.get('value'):
|
|
16
|
+
qs = qs.filter(pk__in=self.request.GET['value'].split(','))
|
|
17
|
+
elif self.q:
|
|
18
|
+
qs = search_queryset(qs, self.q, ('name', 'slug'))
|
|
19
|
+
return qs
|
|
Binary file
|
|
Binary file
|
|
@@ -15,7 +15,7 @@ simo/automation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
15
15
|
simo/automation/app_widgets.py,sha256=gaqImMZjuMHm7nIb9a4D-Y3qipz_WhSPAHXcwGx4Uzs,199
|
|
16
16
|
simo/automation/controllers.py,sha256=Ow8xG9hkdyMRZbrNPX5uZloYM9jZqa9mgCh4k6FeoJw,11492
|
|
17
17
|
simo/automation/forms.py,sha256=UWnkxw8pILPK0smRPTo4SLgsZl78zOySx7JIc30Bgtk,10228
|
|
18
|
-
simo/automation/gateways.py,sha256=
|
|
18
|
+
simo/automation/gateways.py,sha256=dTrx4r3aoUynWQCHHXZFKkoHhKbC3-UMZIY755C-sdI,15470
|
|
19
19
|
simo/automation/helpers.py,sha256=iP-fxxB8HsFQy3k2CjFubu86aMqvWgmh-p24DiyOrek,4330
|
|
20
20
|
simo/automation/models.py,sha256=l45FHgeKGsfpLtd1X1PVFpIjB5JI4BlvKkodpcxm6aE,927
|
|
21
21
|
simo/automation/serializers.py,sha256=PjyFrjdPK1mBsgbNhyqMi9SWzcymqTa742ipy0LhAN4,1996
|
|
@@ -24,10 +24,10 @@ simo/automation/__pycache__/__init__.cpython-38.pyc,sha256=YmP0xAD-mxpQHgdTZeC64
|
|
|
24
24
|
simo/automation/__pycache__/app_widgets.cpython-38.pyc,sha256=7DfUA9V_1MiwrOe_ta-ts8dYY8xXb9UMg2_9A3XoRcs,523
|
|
25
25
|
simo/automation/__pycache__/controllers.cpython-38.pyc,sha256=CL-0Tq9B4-E36fYfWT1XEBTq1dkq1W8003f6MrBnQU0,8391
|
|
26
26
|
simo/automation/__pycache__/forms.cpython-38.pyc,sha256=cpA5hA2Iz3JsPC0Dq01ki1I7S9c5DKRcXveHApI1dJo,7772
|
|
27
|
-
simo/automation/__pycache__/gateways.cpython-38.pyc,sha256=
|
|
28
|
-
simo/automation/__pycache__/helpers.cpython-38.pyc,sha256=
|
|
29
|
-
simo/automation/__pycache__/models.cpython-38.pyc,sha256=
|
|
30
|
-
simo/automation/__pycache__/serializers.cpython-38.pyc,sha256=
|
|
27
|
+
simo/automation/__pycache__/gateways.cpython-38.pyc,sha256=F4zO0G15gGMSaQaB_fW13qtcBHQ3KYlDqZ4_Ch0YW70,10956
|
|
28
|
+
simo/automation/__pycache__/helpers.cpython-38.pyc,sha256=fNjSyn4Mfq7-JQx-bdsnj-rSxgu20dVJ9-5ZEMT6yiM,3627
|
|
29
|
+
simo/automation/__pycache__/models.cpython-38.pyc,sha256=VeQNAygVr0AXPlF5LEYk90Tq8zuCVPfsA2r1NBjrkxU,1230
|
|
30
|
+
simo/automation/__pycache__/serializers.cpython-38.pyc,sha256=9Te21FW5-Tki1a-tq3gt0rme0afBA8o-7V249b4muFk,3405
|
|
31
31
|
simo/automation/__pycache__/state.cpython-38.pyc,sha256=TO2IM6h2hbGVlOUcoMwHkDUF4V-54d_KVhcebMgNtCk,784
|
|
32
32
|
simo/automation/migrations/0001_initial.py,sha256=VB6WIK1RlUdtqlWYCEhtnVE24odp2dfUvOVcxUZPpQ4,990
|
|
33
33
|
simo/automation/migrations/0002_update_helpers_in_scripts.py,sha256=GHtc8ibfURDVoWHw17UxaaA0sEy4tIklIjP6GEMLjhs,714
|
|
@@ -63,7 +63,7 @@ simo/core/__init__.py,sha256=_s2TjJfQImsMrTIxqLAx9AZie1Ojmm6sCHASdl3WLGU,50
|
|
|
63
63
|
simo/core/admin.py,sha256=j07Dy3IsW7SRRsAJ2XXGzE0MTxmfY87CEEbT22kLlS4,18550
|
|
64
64
|
simo/core/api.py,sha256=D5FBWvhYpQeM9wVfapzRvBi_ypOtXBt9tmmCaUxpGjI,29992
|
|
65
65
|
simo/core/api_auth.py,sha256=vCxvczA8aWNcW0VyKs5WlC_ytlqeGP_H_hkKUNVkCwM,1247
|
|
66
|
-
simo/core/api_meta.py,sha256=
|
|
66
|
+
simo/core/api_meta.py,sha256=Bh-UOzANXl9Bg3FadFf7biM_olAr9GgjNJXu55SO6Og,5290
|
|
67
67
|
simo/core/app_widgets.py,sha256=VxZzapuc-a29wBH7JzpvNF2SK1ECrgNUySId5ke1ffc,2509
|
|
68
68
|
simo/core/apps.py,sha256=CsqpiQerhmrMsH-wGiG-gQgXd9qEkIi-LUaA9cXpKSw,425
|
|
69
69
|
simo/core/auto_urls.py,sha256=FBDclIeRp5UVWomIUbRzUgY-AoMk-r2qC2htlwKD4Lo,1106
|
|
@@ -74,8 +74,8 @@ simo/core/controllers.py,sha256=gVwQHYkJ6GNTHaKTSjf4H2VVykQbvKh4_fSe_MdAVi4,3741
|
|
|
74
74
|
simo/core/dynamic_settings.py,sha256=bUs58XEZOCIEhg1TigR3LmYggli13KMryBZ9pC7ugAQ,1872
|
|
75
75
|
simo/core/events.py,sha256=1_KIk5pJqdLPRQlCQ9xSyALst2Cn0b2lAEAJ3QjwIjE,4801
|
|
76
76
|
simo/core/filters.py,sha256=6wbn8C2WvKTTjtfMwwLBp2Fib1V0-DMpS4iqJd6jJQo,2540
|
|
77
|
-
simo/core/form_fields.py,sha256=
|
|
78
|
-
simo/core/forms.py,sha256=
|
|
77
|
+
simo/core/form_fields.py,sha256=Os4bLhEt6fQpQ5JWPThs5XxMI2429kQNgr7SgDDr_y0,5063
|
|
78
|
+
simo/core/forms.py,sha256=iPUBclY5aSX4fCy2VdAMi48De95lj17RiQaggAKmTnA,21860
|
|
79
79
|
simo/core/gateways.py,sha256=Y2BME6zSyeUq_e-hzEUF6gErCUCP6nFxedkLZKiLVOo,4141
|
|
80
80
|
simo/core/loggers.py,sha256=EBdq23gTQScVfQVH-xeP90-wII2DQFDjoROAW6ggUP4,1645
|
|
81
81
|
simo/core/managers.py,sha256=n-b3I4uXzfHKTeB1VMjSaMsDUxp8FegFJwnbV1IsWQ4,3019
|
|
@@ -83,7 +83,7 @@ simo/core/middleware.py,sha256=eUFf6iP-Snx_0TE3MoXsSwqrd5IjlukqZk2GQGStRCo,3385
|
|
|
83
83
|
simo/core/models.py,sha256=-zhQEvQRqacTjdqL4Gv7shlP1Uo09Rj3vHKqNONlxWU,22716
|
|
84
84
|
simo/core/permissions.py,sha256=2YNRot2qoHjHKWPGOpO4PBseecctPbTlUQpepnFkCRs,3027
|
|
85
85
|
simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
|
|
86
|
-
simo/core/serializers.py,sha256=
|
|
86
|
+
simo/core/serializers.py,sha256=ikt1_UzEqJKPC1UFvvvf6q424VXkCY1oh61uXTDBeYc,22624
|
|
87
87
|
simo/core/signal_receivers.py,sha256=y8p0BG3PzhHI3w2WXS8QXyxXc7YKUE_mmO2-QElvrP4,6276
|
|
88
88
|
simo/core/socket_consumers.py,sha256=Es_NmacQGZjsncBXDTEXR2yZbRs7mf2FKOBJjbZRGac,9607
|
|
89
89
|
simo/core/storage.py,sha256=_5igjaoWZAiExGWFEJMElxUw55DzJG1jqFty33xe8BE,342
|
|
@@ -93,10 +93,10 @@ simo/core/types.py,sha256=WJEq48mIbFi_5Alt4wxWMGXxNxUTXqfQU5koH7wqHHI,1108
|
|
|
93
93
|
simo/core/views.py,sha256=yx9I0byeVUa-LAOnklpWIYwpNNOf5m9fyjKBvj4YCh4,2475
|
|
94
94
|
simo/core/widgets.py,sha256=J9e06C6I22F6xKic3VMgG7WeX07glAcl-4bF2Mg180A,2827
|
|
95
95
|
simo/core/__pycache__/__init__.cpython-38.pyc,sha256=ZJFM_XN0RmJMULQulgA_wFiOnEtsMoedcOWnXjH-Y8o,208
|
|
96
|
-
simo/core/__pycache__/admin.cpython-38.pyc,sha256=
|
|
96
|
+
simo/core/__pycache__/admin.cpython-38.pyc,sha256=zdegA3IsH3QhT7Hm6Aj08F2sv-3h1X7VBcwN05fhVis,14155
|
|
97
97
|
simo/core/__pycache__/api.cpython-38.pyc,sha256=JXCs5U9MPyZTdO4_j-ytpH1_Fo9-w36zs1eHXZ-czwo,22925
|
|
98
98
|
simo/core/__pycache__/api_auth.cpython-38.pyc,sha256=mi3mu5qEKio_PvfQEvr3Q6AhdPLAHxzxAxrMbAz_pKU,1712
|
|
99
|
-
simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=
|
|
99
|
+
simo/core/__pycache__/api_meta.cpython-38.pyc,sha256=euP2EQsfTVCdvMT9NY10bK7xrz2dQouqQKZP0efN1ss,3906
|
|
100
100
|
simo/core/__pycache__/app_widgets.cpython-38.pyc,sha256=oN657XMMZ6GYN9nblv7fX3kdnTEzSP9XV6PXM6Z0wl4,4358
|
|
101
101
|
simo/core/__pycache__/apps.cpython-38.pyc,sha256=JL0BEqgXcSQvMlcK48PBpPfyDEkPMdO1Y0teqMRGirs,713
|
|
102
102
|
simo/core/__pycache__/auto_urls.cpython-38.pyc,sha256=ib_ns5Ko8ybfrdJJWYVV1jevihxOFs39aBF4bez6Lzs,874
|
|
@@ -107,18 +107,18 @@ simo/core/__pycache__/controllers.cpython-38.pyc,sha256=LtrQQ8egOIOuQbAckeM-z8Of
|
|
|
107
107
|
simo/core/__pycache__/dynamic_settings.cpython-38.pyc,sha256=wGpnscX1DxFpRl54MQURhjz2aD3NJohSzw9JCFnzh2Y,2384
|
|
108
108
|
simo/core/__pycache__/events.cpython-38.pyc,sha256=1y8YaZsiDkBOeIWzH7SQz4holmMG_RLlMWi8kuSZcoE,5280
|
|
109
109
|
simo/core/__pycache__/filters.cpython-38.pyc,sha256=WBBDwcDQwOmgbrRhyUxenSN80rU4Eq9jQ6RcrRGCP_o,2440
|
|
110
|
-
simo/core/__pycache__/form_fields.cpython-38.pyc,sha256=
|
|
111
|
-
simo/core/__pycache__/forms.cpython-38.pyc,sha256=
|
|
110
|
+
simo/core/__pycache__/form_fields.cpython-38.pyc,sha256=WJgjOqvl5BZoVAGVtxGeDOOW-jn3_fdJwVYBx1IRJlY,5886
|
|
111
|
+
simo/core/__pycache__/forms.cpython-38.pyc,sha256=Ye8lP-xG_yxMKOftzhXNPWfY4nkjNynBn-eJhLnb-GM,17754
|
|
112
112
|
simo/core/__pycache__/gateways.cpython-38.pyc,sha256=-_ugqnUOA1Cl6VfMqpV96n7ekVOEwYg_jNvoaZEcx9I,4815
|
|
113
113
|
simo/core/__pycache__/loggers.cpython-38.pyc,sha256=Z-cdQnC6XlIonPV4Sl4E52tP4NMEdPAiHK0cFaIL7I8,1623
|
|
114
114
|
simo/core/__pycache__/managers.cpython-38.pyc,sha256=6RTIxyjOgpQGtAqcUyE2vFPS09w1V5Wmd_vOV7rHRRI,3370
|
|
115
115
|
simo/core/__pycache__/middleware.cpython-38.pyc,sha256=SgTLFNkKxvJ62hevSAVNZHgHdG_u2p7AZBhrj-jfFPs,2649
|
|
116
|
-
simo/core/__pycache__/models.cpython-38.pyc,sha256=
|
|
116
|
+
simo/core/__pycache__/models.cpython-38.pyc,sha256=3nVIrsYP-ZCmkr5z71zivCdaZ8hqmh521BvlMK5gP6g,18468
|
|
117
117
|
simo/core/__pycache__/permissions.cpython-38.pyc,sha256=UdtxCTXPEbe99vgZOfRz9wfKSYvUn9hSRbpIV9CJSyI,2988
|
|
118
118
|
simo/core/__pycache__/routing.cpython-38.pyc,sha256=3T3FPJ8Cn99xZCGvMyg2xjl7al-Shm9CelbSpkJtNP8,599
|
|
119
|
-
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=
|
|
119
|
+
simo/core/__pycache__/serializers.cpython-38.pyc,sha256=SkPKqNRo4PBdHBqJ6KsX5SnJBkC6zk3SO8bpr4enwu4,20000
|
|
120
120
|
simo/core/__pycache__/signal_receivers.cpython-38.pyc,sha256=v-qSKC9KX--aw9-vSNX8z8HXNFr0yOII0Aw8JxrYM0U,4920
|
|
121
|
-
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=
|
|
121
|
+
simo/core/__pycache__/socket_consumers.cpython-38.pyc,sha256=Mr1-x-vGjBNffbz0S6AKpJCuzHJgRm8kXefv3qVVY_E,8397
|
|
122
122
|
simo/core/__pycache__/storage.cpython-38.pyc,sha256=9R1Xu0FJDflfRXUPsqEgt0SpwiP7FGk7HaR8s8XRyI8,721
|
|
123
123
|
simo/core/__pycache__/tasks.cpython-38.pyc,sha256=-J2is-l5XsfhamreN2TPQDTK-Jw6XGYL81bcVfjXsU8,11213
|
|
124
124
|
simo/core/__pycache__/todos.cpython-38.pyc,sha256=lOqGZ58siHM3isoJV4r7sg8igrfE9fFd-jSfeBa0AQI,253
|
|
@@ -237,6 +237,7 @@ simo/core/migrations/0043_alter_category_instance_alter_instance_timezone_and_mo
|
|
|
237
237
|
simo/core/migrations/0044_alter_gateway_type.py,sha256=xoQvOSz_JrWHECAAII83518tmhEEfLUHqxpIjoo4oLY,758
|
|
238
238
|
simo/core/migrations/0045_alter_instance_device_report_history_days_and_more.py,sha256=saR7gEbTDfXTcKnT1R193Aboqlg32HvDRI_JAvZ97TY,1360
|
|
239
239
|
simo/core/migrations/0046_component_value_translation_alter_gateway_type.py,sha256=SUybDSLRCGevVS9mCQGvozO8LA43tKze3R5rCf1TQ4E,1282
|
|
240
|
+
simo/core/migrations/0047_alter_component_value_translation.py,sha256=3GAgUBkZKUwWJMbDJxJJLBicC8eKkQ2ZJA__-xYpBCo,733
|
|
240
241
|
simo/core/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
241
242
|
simo/core/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=w6GiBXVxWj30Bg4Sn_pFVeA041d-pCrkaq8mR3KuF70,5381
|
|
242
243
|
simo/core/migrations/__pycache__/0002_load_icons.cpython-38.pyc,sha256=Nb9RrPjVYo_RpZ5PmzoaEIWGCeVt4kicpmGiKlBrpIw,2123
|
|
@@ -284,6 +285,7 @@ simo/core/migrations/__pycache__/0043_alter_category_instance_alter_instance_tim
|
|
|
284
285
|
simo/core/migrations/__pycache__/0044_alter_gateway_type.cpython-38.pyc,sha256=KwqGKoo8C1wH9ZUhagpC3plTwheSMcWtwlCGcSPd5WQ,964
|
|
285
286
|
simo/core/migrations/__pycache__/0045_alter_instance_device_report_history_days_and_more.cpython-38.pyc,sha256=e1_hKjdokggnPndFkoBWrHQ18IkBi2W7WahcSjAbvKo,1278
|
|
286
287
|
simo/core/migrations/__pycache__/0046_component_value_translation_alter_gateway_type.cpython-38.pyc,sha256=0WowsGpjyPX7Z341bhU4bXErZqqFZaL1gtiusabrD0I,1445
|
|
288
|
+
simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-38.pyc,sha256=ucmaVOjI3q78vBTiEC7Aq76CklWq3fsC24EiH-mIzGc,961
|
|
287
289
|
simo/core/migrations/__pycache__/__init__.cpython-38.pyc,sha256=VZmDQ57BTcebuM0KMhjiTOabgWZCBxQmSJzWZos9SO8,169
|
|
288
290
|
simo/core/static/ansi_styles.css,sha256=4ieJGrjZPKyPSago9FdB_gflHoGE1vxCHi8qVn5tY-Y,37352
|
|
289
291
|
simo/core/static/admin/Img/plus.svg,sha256=2NpSFPWqGIjpAQGFI7LDQHPKagEhYkJiJX95ufCoZaI,741
|
|
@@ -10201,7 +10203,7 @@ simo/core/templates/admin/gateway_control/widget_internals.html,sha256=6UsVKQtHW
|
|
|
10201
10203
|
simo/core/templates/admin/users/qr_code.html,sha256=kE4WNSVsPUvNUFnSUAY8jiD9JCvc6YasIS9vLuw0cbI,125
|
|
10202
10204
|
simo/core/templates/admin/wizard/discovery.html,sha256=xpAiXgKneT0d53c7h1MyAjoOFdXc_lDaH9TdelrggVU,6608
|
|
10203
10205
|
simo/core/templates/admin/wizard/field.html,sha256=ZbgzAUMs6RdJDH44yQ3-rmAkPmBdsIvBTk1RAQaENAs,413
|
|
10204
|
-
simo/core/templates/admin/wizard/wizard_add.html,sha256=
|
|
10206
|
+
simo/core/templates/admin/wizard/wizard_add.html,sha256=ULT1Bj--YnMJ2uVs4zfI6hGZ4zNWTVLLnbADL4ATtLk,4093
|
|
10205
10207
|
simo/core/templates/core/icon_acutocomplete_select_item.html,sha256=D7aWefAJjrDqyMcwt4vtuwkruklJ1aSjCTi99HLrQUY,768
|
|
10206
10208
|
simo/core/templates/core/object_acutocomplete_select_item.html,sha256=pS8APlv1IdhfttONh3npzQNfrOhj63YC7837tnOfSHk,465
|
|
10207
10209
|
simo/core/templates/core/openvpn_client.conf,sha256=z1838G8v8vmIiQKyfE8URCCMpLsges5jbX3hDJkztF4,249
|
|
@@ -10276,16 +10278,16 @@ simo/fleet/__pycache__/auto_urls.cpython-38.pyc,sha256=jHsvfwAumiBusr91QK1-qC-nm
|
|
|
10276
10278
|
simo/fleet/__pycache__/base_types.cpython-38.pyc,sha256=deyPwjpT6xZiFxBGFnj5b7R-lbdOTh2krgpJhrcGVhc,274
|
|
10277
10279
|
simo/fleet/__pycache__/ble.cpython-38.pyc,sha256=Nrof9w7cm4OlpFWHeVnmvvanh2_oF9oQ3TknJiV93-0,1267
|
|
10278
10280
|
simo/fleet/__pycache__/controllers.cpython-38.pyc,sha256=vH7mK1K4JBcLU9eKtqTJwbgB0SFMJ-s7WvO0qOsWjrg,24739
|
|
10279
|
-
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=
|
|
10281
|
+
simo/fleet/__pycache__/forms.cpython-38.pyc,sha256=hrNfyGm2NfoNG1II-OqeHzR2TkkAWp3igvHGs6X0iIM,45252
|
|
10280
10282
|
simo/fleet/__pycache__/gateways.cpython-38.pyc,sha256=MIpXuGWitGNdsxJ99fWvMXJ6sVE96ac7iR4K4aM4Sds,5148
|
|
10281
10283
|
simo/fleet/__pycache__/managers.cpython-38.pyc,sha256=Vmm23zoQnS3-uS5_WJt2n3wtjhLiEhLWaYxXJCU6Gts,1339
|
|
10282
10284
|
simo/fleet/__pycache__/models.cpython-38.pyc,sha256=AXk1Q_nnHDXirHYgM3EW5pLsrR2CaPWk4EuvGCuDUpI,14131
|
|
10283
10285
|
simo/fleet/__pycache__/routing.cpython-38.pyc,sha256=aPrCmxFKVyB8R8ZbJDwdPdFfvT7CvobovvZeq_mqRgY,314
|
|
10284
10286
|
simo/fleet/__pycache__/serializers.cpython-38.pyc,sha256=l_FzORWCM1hcSZV0AaGRO-p0CMTcEfqnLGgbn2IVvI0,3648
|
|
10285
|
-
simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=
|
|
10287
|
+
simo/fleet/__pycache__/socket_consumers.cpython-38.pyc,sha256=lEC1SkY_KgRY0QoBUMPjnbFwSa7qmCf-4eNQ45hAy68,14141
|
|
10286
10288
|
simo/fleet/__pycache__/tasks.cpython-38.pyc,sha256=RoNxL2WUiW67s9O9DjaYVVjCBSZu2nje0Qn9FJkWVS0,1116
|
|
10287
10289
|
simo/fleet/__pycache__/utils.cpython-38.pyc,sha256=obUd-X2Y-ybx4icqUWq_qwIxrP9yyarJjexWAfO4MTI,3344
|
|
10288
|
-
simo/fleet/__pycache__/views.cpython-38.pyc,sha256=
|
|
10290
|
+
simo/fleet/__pycache__/views.cpython-38.pyc,sha256=awPe_fz7V5DgknQGEyHqbOFhX6iBhK7Y5TIa7zcO-so,4342
|
|
10289
10291
|
simo/fleet/migrations/0001_initial.py,sha256=lce8nkD8Sz6pYr-XJSpDm4CMDuB6TA__WtnHpIp-eA4,1326
|
|
10290
10292
|
simo/fleet/migrations/0002_auto_20220422_0743.py,sha256=sFOfAjnQOzcJjE8lHrrHgTaGilJNYswMdXphgVzUZqY,825
|
|
10291
10293
|
simo/fleet/migrations/0003_auto_20220422_0752.py,sha256=VcH7DyMAniEwT76hDVofS8FTNpM3nxz_J9AC2zKHDSA,543
|
|
@@ -10374,27 +10376,28 @@ simo/fleet/migrations/__pycache__/0040_alter_colonel_pwm_frequency.cpython-38.py
|
|
|
10374
10376
|
simo/fleet/migrations/__pycache__/0041_alter_colonel_instance_and_more.cpython-38.pyc,sha256=76yu9gz3pcAq5IYbNeZIoOSgdi0HVqTvc3EdXLGriQI,1178
|
|
10375
10377
|
simo/fleet/migrations/__pycache__/0042_auto_20241120_1028.cpython-38.pyc,sha256=yK2HRc7MYMc4i9ev7FaguBdnXUnUmpFn8E8JOP_yluA,1030
|
|
10376
10378
|
simo/fleet/migrations/__pycache__/0043_auto_20241203_0930.cpython-38.pyc,sha256=0QWVIvorcCuhfuGFu0fMdu5vkxcQSosxjt8KT6Ld07E,980
|
|
10379
|
+
simo/fleet/migrations/__pycache__/0044_auto_20241210_0707.cpython-38.pyc,sha256=M99PMBDgOdS_0KIEhlUamHWeTVCTdIHFXIvYTRX15Z8,1029
|
|
10377
10380
|
simo/fleet/migrations/__pycache__/__init__.cpython-38.pyc,sha256=5k1KW0jeSDzw6RnVPRq4CaO13Lg7M0F-pxA_gqqZ6Mg,170
|
|
10378
10381
|
simo/fleet/templates/fleet/controllers_info/Button.md,sha256=GIuxqG617174NEtpPeCGVocxO4YMe7-CacgVSu_L5-E,739
|
|
10379
10382
|
simo/fleet/templates/fleet/controllers_info/ENS160AirQualitySensor.md,sha256=3LSTY9YPFuVPIbVsYCAifcotrXJcOXl2k774_vo6nAE,770
|
|
10380
10383
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10381
10384
|
simo/generic/app_widgets.py,sha256=y8W3jR76Hh26O9pPQyg2SophMbYIOtAWD33MPKbB8Mg,856
|
|
10382
10385
|
simo/generic/base_types.py,sha256=u3SlfpNYaCwkVBwomWgso4ODzL71ay9MhiAW-bxgnDU,341
|
|
10383
|
-
simo/generic/controllers.py,sha256=
|
|
10384
|
-
simo/generic/forms.py,sha256=
|
|
10385
|
-
simo/generic/gateways.py,sha256=
|
|
10386
|
+
simo/generic/controllers.py,sha256=gqL1Evt-8Cq8MeHG-eV8aCtQ4St_gylE52wnXwOQUWU,46285
|
|
10387
|
+
simo/generic/forms.py,sha256=AIY9w8wNq2-Jwo2ekq2yjdSTZzqDFr70ZDcmT4kaU4Q,24381
|
|
10388
|
+
simo/generic/gateways.py,sha256=Dm1Yb7JtSbqeo4AIbsHvFK3Og7ZCWHw71BZY8wwAkWY,17466
|
|
10386
10389
|
simo/generic/models.py,sha256=Adq7ipWK-renxJlNW-SZnAq2oGEOwKx8EdUWaKnfcVQ,7597
|
|
10387
10390
|
simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
|
|
10388
10391
|
simo/generic/socket_consumers.py,sha256=pyiqzfGxSKBNqfrfEJ_kCU0UbSC28XnvDn6QjKkbqyY,1767
|
|
10389
10392
|
simo/generic/__pycache__/__init__.cpython-38.pyc,sha256=mLu54WS9KIl-pHwVCBKpsDFIlOqml--JsOVzAUHg6cU,161
|
|
10390
10393
|
simo/generic/__pycache__/app_widgets.cpython-38.pyc,sha256=D9b13pbMlirgHmjDnQhfLIDGSVINoSouHb4SWOeCRrs,1642
|
|
10391
10394
|
simo/generic/__pycache__/base_types.cpython-38.pyc,sha256=aV5NdIuvXR-ItKpI__MwcyPZHD6Z882TFdgYkPCkr1I,493
|
|
10392
|
-
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10393
|
-
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=
|
|
10394
|
-
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=
|
|
10395
|
+
simo/generic/__pycache__/controllers.cpython-38.pyc,sha256=jJjwKVaDYyazrRGNjUFoY74nr_jX_DEnsC9KjyxZCgc,30427
|
|
10396
|
+
simo/generic/__pycache__/forms.cpython-38.pyc,sha256=rNLPZ5K45hNf4Hx7QvcNFkIdUrX1CSltDA-TwkDnbUs,18460
|
|
10397
|
+
simo/generic/__pycache__/gateways.cpython-38.pyc,sha256=ZoHZv3_kjOqfFqzs4MmgZ22-u1d3mbBO9PmBycDVKU0,12823
|
|
10395
10398
|
simo/generic/__pycache__/models.cpython-38.pyc,sha256=MZpum7syAFxuulf47K7gtUlJJ7xRD-IBUBAwUM1ZRnw,5825
|
|
10396
10399
|
simo/generic/__pycache__/routing.cpython-38.pyc,sha256=xtxTUTBTdivzFyA5Wh7k-hUj1WDO_FiRq6HYXdbr9Ks,382
|
|
10397
|
-
simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=
|
|
10400
|
+
simo/generic/__pycache__/socket_consumers.cpython-38.pyc,sha256=FaVCf_uJI2uwj1Zz-jwsOXou65oV9gFCIB8e-YKquRk,1662
|
|
10398
10401
|
simo/generic/migrations/0001_initial.py,sha256=7FpPcfpRU5ya0b8s2KbxR5a3npf92YruvZltUybjzys,676
|
|
10399
10402
|
simo/generic/migrations/0002_auto_20241126_0726.py,sha256=SX38JwP732QooOm5HM1Xo7Th_Mv_6YZloT3eozULOhs,922
|
|
10400
10403
|
simo/generic/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -10427,33 +10430,38 @@ simo/generic/templates/admin/controller_widgets/weather.html,sha256=84SESQBhhzNU
|
|
|
10427
10430
|
simo/generic/templates/generic/controllers_info/dummy.md,sha256=DcdkpYXpK7sroINukZZPUQs9uekN9kkE7p5hfnArgFo,147
|
|
10428
10431
|
simo/generic/templates/generic/controllers_info/stateselect.md,sha256=T0w3vJg02W3RMSsljN1EPRnkVaeRW5acSZaSq9FYvZw,135
|
|
10429
10432
|
simo/multimedia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10430
|
-
simo/multimedia/admin.py,sha256=
|
|
10433
|
+
simo/multimedia/admin.py,sha256=S7WYYTwsd73WVU60MDVsheyRH9bDnsMZezV_kPJhYZ0,1031
|
|
10431
10434
|
simo/multimedia/api.py,sha256=mZ5BTggWdc_kL8P70JGC3rTCiZKPnxWYoyNcAQkFnX4,285
|
|
10432
10435
|
simo/multimedia/app_widgets.py,sha256=g_IPx5bNmIS6JbaXXDCzYZYV2KVKAiYvWjH4oI30lWM,331
|
|
10436
|
+
simo/multimedia/auto_urls.py,sha256=9FUwlifvAM-AJbAVK6ZCjsQdAZfREuf_sf-kSYjMu7I,204
|
|
10433
10437
|
simo/multimedia/base_types.py,sha256=dAP7_uh_b3A03yXBJZyQdRFucKIro4_RkIZ5yOaWXVE,151
|
|
10434
|
-
simo/multimedia/controllers.py,sha256=
|
|
10438
|
+
simo/multimedia/controllers.py,sha256=pLrJew-WJloR7MGO6hlnIBCAalezasmHLcp1v0vBTWA,3539
|
|
10435
10439
|
simo/multimedia/forms.py,sha256=oMCVUXRNiESrY3w_uBLRRgjMjx8BrmNeVglzorA9QtY,239
|
|
10436
|
-
simo/multimedia/models.py,sha256=
|
|
10437
|
-
simo/multimedia/requirements.txt,sha256=QeIhjf1RfNGCYn_WZm3VuinPI2wK31WEJPbCxRWxssY,28
|
|
10440
|
+
simo/multimedia/models.py,sha256=qUQaADxFegVMbcEdjyP72UCq5kkqJ5ZSe2lu9qyoom8,1169
|
|
10438
10441
|
simo/multimedia/serializers.py,sha256=9DRGsJVJLKdqmOLiVHMY06bTTYxpABhDy1JB_klzsBw,383
|
|
10442
|
+
simo/multimedia/views.py,sha256=oFhtJQJT5-XRtzoIKo7SWqLydCB9AWzcj2a-kQ5P7dw,558
|
|
10439
10443
|
simo/multimedia/__pycache__/__init__.cpython-38.pyc,sha256=BOLHOifu6r_MuWjddGcQVsYkqYlkmHvPQIcx3selLIk,164
|
|
10440
|
-
simo/multimedia/__pycache__/admin.cpython-38.pyc,sha256=
|
|
10444
|
+
simo/multimedia/__pycache__/admin.cpython-38.pyc,sha256=xIax_AtzQlJiQmEBG5xuhJz2-Ztf40e26AQs5oBISfw,1309
|
|
10441
10445
|
simo/multimedia/__pycache__/api.cpython-38.pyc,sha256=lFGEB74vgyEM98B42wwcN9WvH8FAupIiSY0SwEBd5Dw,605
|
|
10442
10446
|
simo/multimedia/__pycache__/app_widgets.cpython-38.pyc,sha256=6pr3fz21tQ5ReC9SJ8VzheUZ0hpxDIClB0SA8YCwcPk,730
|
|
10447
|
+
simo/multimedia/__pycache__/auto_urls.cpython-38.pyc,sha256=JNI3pZNFC3NoJV4cxsy-Oe6Vc6TA9fpPU63hjlXWINE,357
|
|
10443
10448
|
simo/multimedia/__pycache__/base_types.cpython-38.pyc,sha256=c4nmNziLs4RB3MAnxltn3W5XNW6PM5_vK_mm3Yvy42Y,324
|
|
10444
|
-
simo/multimedia/__pycache__/controllers.cpython-38.pyc,sha256=
|
|
10449
|
+
simo/multimedia/__pycache__/controllers.cpython-38.pyc,sha256=aeAYsu7v1HH-Or9IDq41TI5SRMakuQYIIR1uwyci2zI,5011
|
|
10445
10450
|
simo/multimedia/__pycache__/forms.cpython-38.pyc,sha256=99h7Yj2jim3QOrqej00wiPufrCF3F--RoYvwa6lzhPI,697
|
|
10446
|
-
simo/multimedia/__pycache__/models.cpython-38.pyc,sha256=
|
|
10451
|
+
simo/multimedia/__pycache__/models.cpython-38.pyc,sha256=LmQ_XMA--wvLq11xYp24nU-y-kbx17iEZ10y9twCMJ0,1662
|
|
10447
10452
|
simo/multimedia/__pycache__/serializers.cpython-38.pyc,sha256=n86txYSrkmN0Xlrr8dMwKSY7rEzMc1iovepCZi_Fcw8,886
|
|
10453
|
+
simo/multimedia/__pycache__/views.cpython-38.pyc,sha256=yq5Hi2HrbSNr8MP4uUZO7_GMeVgqg21R6yFe85zNNhM,899
|
|
10448
10454
|
simo/multimedia/migrations/0001_initial.py,sha256=YxTbmI-aF9OZUkFPnCNqV3t3r5nSJg59pKcTvm-ZYbU,610
|
|
10449
10455
|
simo/multimedia/migrations/0002_sound_length.py,sha256=XpPemInQwL1QsiqhUPkdBPBYI2E5gDPyC_1vhyImq5M,471
|
|
10450
10456
|
simo/multimedia/migrations/0003_alter_sound_length.py,sha256=tt1OJVkrCo6Ybws1mGobdvTP5o68P3-cHZdGG_PeZwU,442
|
|
10451
10457
|
simo/multimedia/migrations/0004_auto_20231023_1055.py,sha256=ilH1o_wxkK5QDjcPEEDhoHWx2GcjZWLG6XjlUfQRmhI,718
|
|
10458
|
+
simo/multimedia/migrations/0005_remove_sound_slug_sound_date_uploaded.py,sha256=SzkgIhCIEVMSmxVwGHQfggdsX4wWybvskqVx-vVp2Qs,602
|
|
10452
10459
|
simo/multimedia/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10453
10460
|
simo/multimedia/migrations/__pycache__/0001_initial.cpython-38.pyc,sha256=slsqUkj8A11Oj5bYJ1s5dS60Qx4H9k_oRZ3HaAhuho4,760
|
|
10454
10461
|
simo/multimedia/migrations/__pycache__/0002_sound_length.cpython-38.pyc,sha256=5Qh_yhupAkn6xcxP_T6KhA2__l6FdQmQb2Y0dzqq33s,678
|
|
10455
10462
|
simo/multimedia/migrations/__pycache__/0003_alter_sound_length.cpython-38.pyc,sha256=dkdqLx_cWLAxxVCUxuuAX39iTv7G5kG-PhJ40HsPzx8,669
|
|
10456
10463
|
simo/multimedia/migrations/__pycache__/0004_auto_20231023_1055.cpython-38.pyc,sha256=tX6x1gNeVcUHcCFvisP9Z2jPBE029TJG632fvtvUjV8,892
|
|
10464
|
+
simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-38.pyc,sha256=vpu4EfpVp5rYRKYEVn4vDylgpeasD31ZV62sNR_HXhY,801
|
|
10457
10465
|
simo/multimedia/migrations/__pycache__/__init__.cpython-38.pyc,sha256=mCgSiQBphL85imdWyTi9-4zBDYF6HfXbhB0ycSPVVuA,175
|
|
10458
10466
|
simo/multimedia/templates/admin/controller_widgets/player.html,sha256=v4PFoL37-C7L6ILZI6yF5ff9iO3EnEs5kXbRayaHy0s,358
|
|
10459
10467
|
simo/notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -10467,7 +10475,7 @@ simo/notifications/__pycache__/admin.cpython-38.pyc,sha256=MScNrtVM1wavefsPfxy0A
|
|
|
10467
10475
|
simo/notifications/__pycache__/api.cpython-38.pyc,sha256=eQmCHwTnr4zQ3ZY_SKZVCryiSEnzmyIjHQM13pZ5LT0,2071
|
|
10468
10476
|
simo/notifications/__pycache__/models.cpython-38.pyc,sha256=PoqLuOnlaAWQQ-20AtqhvAlLSkakPmdn7J7wGvHNW3g,2449
|
|
10469
10477
|
simo/notifications/__pycache__/serializers.cpython-38.pyc,sha256=7-eRGKYuQ4g1SpKOMpz17SIiu1HmaMoYv-cJbaO9QGA,1028
|
|
10470
|
-
simo/notifications/__pycache__/utils.cpython-38.pyc,sha256=
|
|
10478
|
+
simo/notifications/__pycache__/utils.cpython-38.pyc,sha256=4ZnI-pmWji84EXBkPrl4ir1kGjfanO4bH5--bLNRxCA,1648
|
|
10471
10479
|
simo/notifications/migrations/0001_initial.py,sha256=Zh69AQ-EKlQKfqfnMDVRcxvo1MxRY-TFLCdnNcgqi6g,2003
|
|
10472
10480
|
simo/notifications/migrations/0002_notification_instance.py,sha256=B3msbMeKvsuq-V7gvRADRjj5PFLayhi3pQvHZjqzO5g,563
|
|
10473
10481
|
simo/notifications/migrations/0003_alter_notification_instance.py,sha256=CXrOkdbXYwlEK5O8iEjDzrocAP5WQ9fQ-0_TcT4VgEA,609
|
|
@@ -10502,7 +10510,7 @@ simo/users/__pycache__/auto_urls.cpython-38.pyc,sha256=bc6BOgghLdMzUroGMj7eB6YX9
|
|
|
10502
10510
|
simo/users/__pycache__/dynamic_settings.cpython-38.pyc,sha256=6F8JBjZkHykySnmZjNEzjS0ijbmPdcp9yUAZ5kqq_Fo,864
|
|
10503
10511
|
simo/users/__pycache__/managers.cpython-38.pyc,sha256=O0Y8ABp42RAosrbODmYsPMaj9AyOPyJ-aqzuO0Qpi2s,679
|
|
10504
10512
|
simo/users/__pycache__/middleware.cpython-38.pyc,sha256=Tj4nVEAvxEW3xA63fBRiJWRJpz_M848ZOqbHioc_IPE,1149
|
|
10505
|
-
simo/users/__pycache__/models.cpython-38.pyc,sha256=
|
|
10513
|
+
simo/users/__pycache__/models.cpython-38.pyc,sha256=qNtAn_eWVmRTWhTxN8GtCc549dcJsTdaF7Uk19yNMgg,18330
|
|
10506
10514
|
simo/users/__pycache__/permissions.cpython-38.pyc,sha256=ez5NxoL_JUeeH6GsKhvFreuA3FCBgGf9floSypdXUtM,633
|
|
10507
10515
|
simo/users/__pycache__/serializers.cpython-38.pyc,sha256=Dy8RAcwNkNSXoJHvLp8fozURyHCtucqpSPyqZtbnMZc,3732
|
|
10508
10516
|
simo/users/__pycache__/sso_urls.cpython-38.pyc,sha256=uAwDozpOmrhUald-8tOHANILXkH7-TI8fNYXOtPkSY8,402
|
|
@@ -10608,9 +10616,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
10608
10616
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10609
10617
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10610
10618
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10611
|
-
simo-2.7.
|
|
10612
|
-
simo-2.7.
|
|
10613
|
-
simo-2.7.
|
|
10614
|
-
simo-2.7.
|
|
10615
|
-
simo-2.7.
|
|
10616
|
-
simo-2.7.
|
|
10619
|
+
simo-2.7.11.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
10620
|
+
simo-2.7.11.dist-info/METADATA,sha256=Jf5swgKHP4RoINsccaxIEMqjQSMRULyR-3IVDej8sq0,1953
|
|
10621
|
+
simo-2.7.11.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
10622
|
+
simo-2.7.11.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
|
|
10623
|
+
simo-2.7.11.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
10624
|
+
simo-2.7.11.dist-info/RECORD,,
|
simo/multimedia/requirements.txt
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|