simo 3.0.1__py3-none-any.whl → 3.0.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.
- simo/automation/gateways.py +32 -16
- simo/fleet/controllers.py +12 -0
- simo/fleet/forms.py +4 -2
- simo/fleet/voice_assistant.py +10 -0
- simo/generic/controllers.py +2 -2
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/METADATA +1 -2
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/RECORD +11 -11
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/WHEEL +0 -0
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/entry_points.txt +0 -0
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/licenses/LICENSE.md +0 -0
- {simo-3.0.1.dist-info → simo-3.0.4.dist-info}/top_level.txt +0 -0
simo/automation/gateways.py
CHANGED
|
@@ -257,23 +257,43 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
257
257
|
# however the process is actually still running
|
|
258
258
|
process.kill()
|
|
259
259
|
self.last_death = time.time()
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if id not in self.terminating_scripts: # was not intentionaly terminated
|
|
265
|
-
if comp:
|
|
260
|
+
# If component exists and is marked running, attempt to persist error
|
|
261
|
+
# BEFORE removing from in-memory tracking, so we can retry if DB is down.
|
|
262
|
+
if comp and comp.value == 'running' and id not in self.terminating_scripts:
|
|
263
|
+
try:
|
|
266
264
|
tz = pytz.timezone(comp.zone.instance.timezone)
|
|
267
265
|
timezone.activate(tz)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
logger = get_component_logger(comp)
|
|
267
|
+
logger.log(logging.INFO, "-------DEAD!-------")
|
|
268
|
+
comp.value = 'error'
|
|
269
|
+
comp.save()
|
|
270
|
+
except Exception:
|
|
271
|
+
# Leave entry in running_scripts to retry on next tick
|
|
272
|
+
continue
|
|
273
|
+
# For any other case or after successful DB update, drop tracking entry
|
|
274
|
+
self.running_scripts.pop(id, None)
|
|
272
275
|
|
|
273
276
|
if self.last_death and time.time() - self.last_death < 5:
|
|
274
277
|
# give 10s air before we wake these dead scripts up!
|
|
275
278
|
return
|
|
276
279
|
|
|
280
|
+
# Reconcile scripts marked as 'running' in DB but not tracked or with dead PID
|
|
281
|
+
for comp in Component.objects.filter(base_type='script', value='running'):
|
|
282
|
+
if comp.id in self.running_scripts:
|
|
283
|
+
continue
|
|
284
|
+
pid = None
|
|
285
|
+
try:
|
|
286
|
+
pid = int(comp.meta.get('pid')) if comp.meta and 'pid' in comp.meta else None
|
|
287
|
+
except Exception:
|
|
288
|
+
pid = None
|
|
289
|
+
is_pid_alive = bool(pid) and os.path.exists(f"/proc/{pid}")
|
|
290
|
+
if not is_pid_alive:
|
|
291
|
+
try:
|
|
292
|
+
comp.value = 'error'
|
|
293
|
+
comp.save(update_fields=['value'])
|
|
294
|
+
except Exception:
|
|
295
|
+
pass
|
|
296
|
+
|
|
277
297
|
for script in Component.objects.filter(
|
|
278
298
|
base_type='script', config__keep_alive=True
|
|
279
299
|
).exclude(value__in=('running', 'stopped', 'finished')):
|
|
@@ -357,13 +377,9 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
357
377
|
print("START SCRIPT %s" % str(component))
|
|
358
378
|
|
|
359
379
|
if component.id in self.running_scripts:
|
|
360
|
-
#
|
|
361
|
-
# so we make sure it has correct value, do nothing else and return!
|
|
380
|
+
# Script appears to be healthy; do nothing and return.
|
|
362
381
|
if component.id not in self.terminating_scripts \
|
|
363
382
|
and self.running_scripts[component.id]['proc'].is_alive():
|
|
364
|
-
if component.value != 'running':
|
|
365
|
-
component.value = 'running'
|
|
366
|
-
component.save()
|
|
367
383
|
return
|
|
368
384
|
|
|
369
385
|
# script is in terminating state or is no longer alive
|
|
@@ -429,4 +445,4 @@ class AutomationsGatewayHandler(GatesHandler, BaseObjectCommandsGatewayHandler):
|
|
|
429
445
|
self.running_scripts.pop(component.id, None)
|
|
430
446
|
logger.handlers = []
|
|
431
447
|
|
|
432
|
-
threading.Thread(target=kill, daemon=True).start()
|
|
448
|
+
threading.Thread(target=kill, daemon=True).start()
|
simo/fleet/controllers.py
CHANGED
|
@@ -991,6 +991,8 @@ class TempHumSensor(FleetDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
|
991
991
|
['temperature', 0, self.sys_temp_units],
|
|
992
992
|
['humidity', 20, '%'],
|
|
993
993
|
['real_feel', 0, self.sys_temp_units],
|
|
994
|
+
['temp_raw', 0, 'C'],
|
|
995
|
+
['hum_raw', 0, '%'],
|
|
994
996
|
['core', 0, 'C'],
|
|
995
997
|
['outside', 0, 'C']
|
|
996
998
|
]
|
|
@@ -1015,6 +1017,8 @@ class TempHumSensor(FleetDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
|
1015
1017
|
['temperature', temp, self.sys_temp_units],
|
|
1016
1018
|
['humidity', humidity, '%'],
|
|
1017
1019
|
['real_feel', 0, self.sys_temp_units],
|
|
1020
|
+
['temp_raw', value.get('temp_raw'), 'C'],
|
|
1021
|
+
['hum_raw', value.get('hum_raw'), '%'],
|
|
1018
1022
|
['core', value.get('core'), 'C'],
|
|
1019
1023
|
['outside', value.get('out'), 'C']
|
|
1020
1024
|
]
|
|
@@ -1034,6 +1038,7 @@ class AmbientLightSensor(FleetDeviceMixin, BaseNumericSensor):
|
|
|
1034
1038
|
gateway_class = FleetGatewayHandler
|
|
1035
1039
|
name = "Ambient lighting sensor"
|
|
1036
1040
|
manual_add = False
|
|
1041
|
+
default_value_units = 'lux'
|
|
1037
1042
|
default_config = {
|
|
1038
1043
|
'widget': 'numeric-sensor',
|
|
1039
1044
|
'value_units': 'lux',
|
|
@@ -1045,6 +1050,7 @@ class AmbientLightSensor(FleetDeviceMixin, BaseNumericSensor):
|
|
|
1045
1050
|
}
|
|
1046
1051
|
|
|
1047
1052
|
|
|
1053
|
+
|
|
1048
1054
|
class RoomPresenceSensor(FleetDeviceMixin, BaseBinarySensor):
|
|
1049
1055
|
gateway_class = FleetGatewayHandler
|
|
1050
1056
|
name = "Human presence sensor"
|
|
@@ -1148,6 +1154,12 @@ class RoomZonePresenceSensor(FleetDeviceMixin, BaseBinarySensor):
|
|
|
1148
1154
|
).publish()
|
|
1149
1155
|
|
|
1150
1156
|
|
|
1157
|
+
class SmokeDetector(FleetDeviceMixin, BaseBinarySensor):
|
|
1158
|
+
name = _("Dust/pollution detector")
|
|
1159
|
+
gateway_class = FleetGatewayHandler
|
|
1160
|
+
manual_add = False
|
|
1161
|
+
|
|
1162
|
+
|
|
1151
1163
|
class VoiceAssistant(FleetDeviceMixin, BaseBinarySensor):
|
|
1152
1164
|
base_type = VoiceAssistantType
|
|
1153
1165
|
name = _("AI Voice Assistant")
|
simo/fleet/forms.py
CHANGED
|
@@ -1815,7 +1815,7 @@ class SentinelDeviceConfigForm(BaseComponentForm):
|
|
|
1815
1815
|
|
|
1816
1816
|
from .controllers import (
|
|
1817
1817
|
RoomSiren, AirQualitySensor, TempHumSensor, AmbientLightSensor,
|
|
1818
|
-
RoomPresenceSensor, VoiceAssistant
|
|
1818
|
+
RoomPresenceSensor, VoiceAssistant, SmokeDetector
|
|
1819
1819
|
)
|
|
1820
1820
|
|
|
1821
1821
|
org_name = self.cleaned_data['name']
|
|
@@ -1827,7 +1827,8 @@ class SentinelDeviceConfigForm(BaseComponentForm):
|
|
|
1827
1827
|
(TempHumSensor, 'temperature-half', 'temperature', 'climate'),
|
|
1828
1828
|
(AmbientLightSensor, 'brightness-low', 'brightness', 'light'),
|
|
1829
1829
|
(RoomPresenceSensor, 'person', 'presence', 'security'),
|
|
1830
|
-
(VoiceAssistant, 'microphone-lines', 'voice assistant', 'other')
|
|
1830
|
+
(VoiceAssistant, 'microphone-lines', 'voice assistant', 'other'),
|
|
1831
|
+
(SmokeDetector, 'fire-smoke', 'dust/pollution', 'security'),
|
|
1831
1832
|
):
|
|
1832
1833
|
default_icon = Icon.objects.filter(slug=icon).first()
|
|
1833
1834
|
self.cleaned_data['icon'] = default_icon.slug if default_icon else org_icon
|
|
@@ -1847,6 +1848,7 @@ class SentinelDeviceConfigForm(BaseComponentForm):
|
|
|
1847
1848
|
)
|
|
1848
1849
|
if form.is_valid():
|
|
1849
1850
|
comp = form.save()
|
|
1851
|
+
comp.value_units = CtrlClass.default_value_units
|
|
1850
1852
|
comp.config['colonel'] = colonel.id
|
|
1851
1853
|
comp.save()
|
|
1852
1854
|
last_comp = comp
|
simo/fleet/voice_assistant.py
CHANGED
|
@@ -65,6 +65,11 @@ class VoiceAssistantSession:
|
|
|
65
65
|
return
|
|
66
66
|
self.active = True
|
|
67
67
|
self.started_ts = time.time()
|
|
68
|
+
# Ensure a fresh session starts gated until arbitration grants winner
|
|
69
|
+
try:
|
|
70
|
+
self._cloud_gate.clear()
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
68
73
|
# is_vo_active will be set by arbitration via open_as_winner
|
|
69
74
|
|
|
70
75
|
async def on_audio_chunk(self, payload: bytes):
|
|
@@ -668,6 +673,11 @@ class VoiceAssistantSession:
|
|
|
668
673
|
self._start_session_notified = False
|
|
669
674
|
self._start_session_inflight = False
|
|
670
675
|
self._prewarm_requested = False
|
|
676
|
+
# Close cloud gate so subsequent sessions don't bypass arbitration
|
|
677
|
+
try:
|
|
678
|
+
self._cloud_gate.clear()
|
|
679
|
+
except Exception:
|
|
680
|
+
pass
|
|
671
681
|
for t in (self._finalizer_task, self._cloud_task, self._play_task, self._followup_task):
|
|
672
682
|
if t and not t.done():
|
|
673
683
|
t.cancel()
|
simo/generic/controllers.py
CHANGED
|
@@ -147,7 +147,7 @@ class Thermostat(ControllerBase):
|
|
|
147
147
|
target_temp = sorted_options[-1][1]
|
|
148
148
|
for timestr, target in sorted_options:
|
|
149
149
|
start_second = int(timestr.split(':')[0]) * 3600 \
|
|
150
|
-
+ int(timestr.split(':')[1] * 60
|
|
150
|
+
+ int(timestr.split(':')[1]) * 60
|
|
151
151
|
if start_second < current_second:
|
|
152
152
|
target_temp = target
|
|
153
153
|
return target_temp
|
|
@@ -364,7 +364,7 @@ class Thermostat(ControllerBase):
|
|
|
364
364
|
self._get_default_user_config()
|
|
365
365
|
)
|
|
366
366
|
self.component.save()
|
|
367
|
-
self.
|
|
367
|
+
self._evaluate()
|
|
368
368
|
|
|
369
369
|
|
|
370
370
|
def hold(self, temperature=None):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simo
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.4
|
|
4
4
|
Summary: Smart Home Supremacy
|
|
5
5
|
Author-email: "Simon V." <simon@simo.io>
|
|
6
6
|
Project-URL: Homepage, https://simo.io
|
|
@@ -33,7 +33,6 @@ Requires-Dist: itsdangerous==2.0.1
|
|
|
33
33
|
Requires-Dist: redis==3.5.3
|
|
34
34
|
Requires-Dist: django-redis==4.12.1
|
|
35
35
|
Requires-Dist: webservices==0.7
|
|
36
|
-
Requires-Dist: websockets==13.1
|
|
37
36
|
Requires-Dist: numpy>=1.24.4
|
|
38
37
|
Requires-Dist: geopy==2.2.0
|
|
39
38
|
Requires-Dist: requests>=2.26.0
|
|
@@ -21,7 +21,7 @@ simo/automation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
21
21
|
simo/automation/app_widgets.py,sha256=gaqImMZjuMHm7nIb9a4D-Y3qipz_WhSPAHXcwGx4Uzs,199
|
|
22
22
|
simo/automation/controllers.py,sha256=jtoG91nYlUPW-Pkl025bBoGELWFm8SQD3duTPsjRhfk,12230
|
|
23
23
|
simo/automation/forms.py,sha256=NAQUS9qrXp2d4GuvdpVyWj0Yh7vqMyX6pzs5oX4ze5Y,9800
|
|
24
|
-
simo/automation/gateways.py,sha256=
|
|
24
|
+
simo/automation/gateways.py,sha256=nqqiNFTYmHnwyYCM2tI-AS4gCnEFPVoJojoMo2mytVM,17383
|
|
25
25
|
simo/automation/helpers.py,sha256=iP-fxxB8HsFQy3k2CjFubu86aMqvWgmh-p24DiyOrek,4330
|
|
26
26
|
simo/automation/models.py,sha256=zt-jkzyq5ddqGT864OkJzCsvov2vZ0nO4ez3hAeZkXg,934
|
|
27
27
|
simo/automation/serializers.py,sha256=Pg-hMaASQPB5_BTAMkfqM6z4jdHWH8xMYWOvDxIvmx8,2126
|
|
@@ -10456,8 +10456,8 @@ simo/fleet/apps.py,sha256=je8mRXMcRq4lABQZlyF2G2hOCkBUicR9I2jvrLDA8eI,238
|
|
|
10456
10456
|
simo/fleet/auto_urls.py,sha256=vrfrooPyY4pDuQjya-eLxCgZldfhwbEeEiXa7diO_CY,847
|
|
10457
10457
|
simo/fleet/base_types.py,sha256=ksJAx-BzUJzv7VvfVxRtDybypHYKPG33UedWRGTBA_4,1243
|
|
10458
10458
|
simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
|
|
10459
|
-
simo/fleet/controllers.py,sha256=
|
|
10460
|
-
simo/fleet/forms.py,sha256=
|
|
10459
|
+
simo/fleet/controllers.py,sha256=BExF9Aw5hUf8JWZwuly7aPqR5pQw1V5AMAAO0JE9WLg,41516
|
|
10460
|
+
simo/fleet/forms.py,sha256=9qJNkItANlZdKBPAUdM00ITTKf0nzf5OTS5P9whwFyE,68994
|
|
10461
10461
|
simo/fleet/gateways.py,sha256=fmtMwoGcJr4ZWjwYvCpYZIr2WdZ2-Lc0KtiKJtfOSQg,6747
|
|
10462
10462
|
simo/fleet/managers.py,sha256=DKU9kv5S6dAqAHWq4OgfEOeK5IJaQW7qdCednA0NpUA,858
|
|
10463
10463
|
simo/fleet/models.py,sha256=itSd-v-t8SXVwxXJKCpL8oYwsNeOXAOqfLAOEdM2AVQ,20558
|
|
@@ -10467,7 +10467,7 @@ simo/fleet/socket_consumers.py,sha256=PBDQphnIQFZ5ThBJmRh2Fxf_k0RITmFktQAPFftOjs
|
|
|
10467
10467
|
simo/fleet/tasks.py,sha256=OYiyhrASyTgLxifhjW9Cx4IaEK6hd1bEXbPGfjIg-zY,1323
|
|
10468
10468
|
simo/fleet/utils.py,sha256=Ev6jl2oW6Gl7O3KwPBi1LDU1gvNpARchcRI4LQZlrEo,9564
|
|
10469
10469
|
simo/fleet/views.py,sha256=3F8im6BsSOaK3KEuBNESE4sDbS_dWHYaOdhTR4cCLjE,5189
|
|
10470
|
-
simo/fleet/voice_assistant.py,sha256=
|
|
10470
|
+
simo/fleet/voice_assistant.py,sha256=pEzSLjaMIubP66ozFXaFMHJCZ-ik0oni70-2ePdg2Eg,40388
|
|
10471
10471
|
simo/fleet/__pycache__/__init__.cpython-312.pyc,sha256=WgOt0Rf4Q4Kz0CyQn-BwX6qKyVcylu4UR1R1bqNKmA0,123
|
|
10472
10472
|
simo/fleet/__pycache__/__init__.cpython-38.pyc,sha256=pIZE7EL6-cuJ3pQtaSwjKLrKLsTYelp1k9sRhXKLh6s,159
|
|
10473
10473
|
simo/fleet/__pycache__/admin.cpython-312.pyc,sha256=-gV2FumLvfZJXhfeRKNI0FxYoQcIbBp_krQlRoulgQs,9997
|
|
@@ -10670,7 +10670,7 @@ simo/fleet/templates/fleet/controllers_info/RoomZonePresenceSensor.md,sha256=Nun
|
|
|
10670
10670
|
simo/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10671
10671
|
simo/generic/app_widgets.py,sha256=y8W3jR76Hh26O9pPQyg2SophMbYIOtAWD33MPKbB8Mg,856
|
|
10672
10672
|
simo/generic/base_types.py,sha256=gJUJYpd_gE-f1ogzagAPA1u2TYljhyU0_SMlgGUvCVk,2318
|
|
10673
|
-
simo/generic/controllers.py,sha256=
|
|
10673
|
+
simo/generic/controllers.py,sha256=oQ7mLYU-MxO4lpCQEGJA0ClIw253Ayzx3pOAFbkqC_4,53273
|
|
10674
10674
|
simo/generic/forms.py,sha256=0RIDtLLzCkiSb9OxlioicOQW9yp1OjLKekpjbxzGVfM,26272
|
|
10675
10675
|
simo/generic/gateways.py,sha256=9K4KkTn0rHRsRba1o8hIQFtRpRtpoL2E33Vozcy-FzM,19458
|
|
10676
10676
|
simo/generic/models.py,sha256=59fkYowOX0imviIhA6uwupvuharrpBykmBm674rJNoI,7279
|
|
@@ -11030,9 +11030,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
11030
11030
|
simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11031
11031
|
simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11032
11032
|
simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11033
|
-
simo-3.0.
|
|
11034
|
-
simo-3.0.
|
|
11035
|
-
simo-3.0.
|
|
11036
|
-
simo-3.0.
|
|
11037
|
-
simo-3.0.
|
|
11038
|
-
simo-3.0.
|
|
11033
|
+
simo-3.0.4.dist-info/licenses/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
|
|
11034
|
+
simo-3.0.4.dist-info/METADATA,sha256=97WF3o8HGc6oNgTGXMBr8SYV-6A3eiYNhpBvmbKWmbA,2224
|
|
11035
|
+
simo-3.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11036
|
+
simo-3.0.4.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
|
|
11037
|
+
simo-3.0.4.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
|
|
11038
|
+
simo-3.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|