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

@@ -1,6 +1,6 @@
1
1
  server{
2
- listen [::]:80 default_server ssl;
3
- listen 80 default_server ssl;
2
+ listen [::]:80 default_server;
3
+ listen 80 default_server;
4
4
 
5
5
  charset utf-8;
6
6
 
simo/core/api.py CHANGED
@@ -14,6 +14,7 @@ from rest_framework.decorators import action
14
14
  from rest_framework.response import Response as RESTResponse
15
15
  from rest_framework.exceptions import ValidationError as APIValidationError
16
16
  from simo.core.utils.config_values import ConfigException
17
+ from simo.users.middleware import introduce as introduce_user
17
18
  from .models import (
18
19
  Instance, Category, Zone, Component, Icon, ComponentHistory,
19
20
  HistoryAggregate, Gateway
simo/core/api_auth.py CHANGED
@@ -1,7 +1,7 @@
1
- import json
2
1
  from rest_framework.authentication import SessionAuthentication, BasicAuthentication
3
2
  from rest_framework import HTTP_HEADER_ENCODING, exceptions
4
3
  from simo.users.models import User
4
+ from simo.users.middleware import introduce as introduce_user
5
5
 
6
6
 
7
7
  class SecretKeyAuth(BasicAuthentication):
@@ -15,7 +15,7 @@ class SecretKeyAuth(BasicAuthentication):
15
15
 
16
16
  if not user or not user.is_active:
17
17
  return
18
-
18
+ introduce_user(user)
19
19
  return (user, None)
20
20
 
21
21
  def authenticate_header(self, request):
@@ -35,6 +35,8 @@ class IsAuthenticated(SessionAuthentication):
35
35
  if not user.is_authenticated:
36
36
  raise exceptions.NotAuthenticated()
37
37
 
38
+ introduce_user(user)
39
+
38
40
  return (user, None)
39
41
 
40
42
  def authenticate_header(self, request):
simo/core/controllers.py CHANGED
@@ -222,13 +222,14 @@ class ControllerBase(ABC):
222
222
  if value != self.component.value:
223
223
  self.component.value_previous = self.component.value
224
224
  self.component.value = value
225
+
225
226
  self.component.change_init_by = None
226
227
  self.component.change_init_date = None
227
228
  self.component.change_init_to = None
228
229
  self.component.change_init_fingerprint = None
229
230
  self.component.save()
230
231
 
231
- def _receive_from_device(self, value, is_alive=True):
232
+ def _receive_from_device(self, value, is_alive=True, battery_level=None):
232
233
  value = self._prepare_for_set(value)
233
234
  actor = self._get_actor(value)
234
235
 
@@ -241,7 +242,9 @@ class ControllerBase(ABC):
241
242
  # in relation to the change of this component
242
243
  introduce(actor)
243
244
  self.component.alive = is_alive
244
- self.component.save(update_fields=['alive'])
245
+ if battery_level:
246
+ self.battery_level = battery_level
247
+ self.component.save(update_fields=['alive', 'battery_level'])
245
248
  self.set(value, actor)
246
249
 
247
250
  if init_by_device and self.component.slaves.count():
@@ -774,7 +777,7 @@ class Lock(Switch):
774
777
  def unlock(self):
775
778
  self.turn_off()
776
779
 
777
- def _receive_from_device(self, value, is_alive=True):
780
+ def _receive_from_device(self, value, is_alive=True, battery_level=None):
778
781
  if type(value) == bool:
779
782
  if value:
780
783
  value = 'locked'
@@ -789,7 +792,9 @@ class Lock(Switch):
789
792
  self.FAULT: 'fault'
790
793
  }
791
794
  value = values_map.get(value, 'fault')
792
- return super()._receive_from_device(value, is_alive=is_alive)
795
+ return super()._receive_from_device(
796
+ value, is_alive=is_alive, battery_level=battery_level
797
+ )
793
798
 
794
799
  def _validate_val(self, value, occasion=None):
795
800
  if occasion == BEFORE_SEND:
simo/fleet/forms.py CHANGED
@@ -106,6 +106,8 @@ class ColonelComponentForm(BaseComponentForm):
106
106
  )
107
107
 
108
108
  def clean_colonel(self):
109
+ if not self.instance.pk:
110
+ return self.cleaned_data['colonel']
109
111
  org = self.instance.config.get('colonel')
110
112
  if org and org != self.cleaned_data['colonel'].id:
111
113
  raise forms.ValidationError(
@@ -618,7 +620,7 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
618
620
  help_text="easeOutSine - offers most naturally looking effect."
619
621
  )
620
622
  inverse = forms.BooleanField(
621
- label=_("Inverse dimmer signal"), required=False
623
+ label=_("Inverse dimmer signal"), required=False, initial=True
622
624
  )
623
625
  on_value = forms.FloatField(
624
626
  required=True, initial=100,
simo/fleet/models.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import requests
2
+ import time
2
3
  from django.db import transaction
3
4
  from django.db import models
4
5
  from django.db.models.signals import post_save, pre_delete, post_delete
@@ -165,7 +166,8 @@ class Colonel(DirtyFieldsMixin, models.Model):
165
166
  @transaction.atomic
166
167
  def rebuild_occupied_pins(self):
167
168
  for pin in ColonelPin.objects.filter(colonel=self):
168
- pin.occupied_by = None
169
+ pin.occupied_by_id = None
170
+ pin.occupied_by_content_type = None
169
171
  pin.save()
170
172
 
171
173
  for component in self.components.all():
@@ -185,38 +187,13 @@ class Colonel(DirtyFieldsMixin, models.Model):
185
187
  interface.scl_pin.save()
186
188
 
187
189
 
188
- @transaction.atomic()
189
190
  def move_to(self, other_colonel):
190
- # TODO: Need to replace pins on components!
191
- other_colonel.refresh_from_db()
192
- assert list(other_colonel.components.all()) == [], \
193
- "Other colonel must be completely empty!"
194
-
195
- for component in self.components.all():
196
- component.config['colonel'] = other_colonel.id
197
- component.save()
198
- self.components.remove(component)
199
- other_colonel.components.add(component)
200
-
201
- other_colonel.i2c_interfaces.all().delete()
202
-
203
- for i2c_interface in self.i2c_interfaces.all():
204
- I2CInterface.objects.create(
205
- no=i2c_interface.no,
206
- colonel=other_colonel, name=i2c_interface.name,
207
- freq=i2c_interface.freq,
208
- scl_pin=ColonelPin.objects.get(
209
- colonel=other_colonel, no=i2c_interface.scl_pin.no,
210
- ),
211
- sda_pin=ColonelPin.objects.get(
212
- colonel=other_colonel, no=i2c_interface.sda_pin.no,
213
- ),
214
- )
215
-
216
- self.rebuild_occupied_pins()
217
- other_colonel.rebuild_occupied_pins()
218
- self.update_config()
219
- other_colonel.update_config()
191
+ self.restart()
192
+ other_colonel.restart()
193
+ time.sleep(1)
194
+ self.uid = other_colonel.uid
195
+ other_colonel.delete()
196
+ self.save()
220
197
 
221
198
 
222
199
  class ColonelPin(models.Model):
@@ -46,6 +46,8 @@ class FleetConsumer(AsyncWebsocketConsumer):
46
46
 
47
47
 
48
48
  async def connect(self):
49
+ print("Fleet Socket Connect with headers:", self.scope.get('headers'))
50
+ await self.accept()
49
51
 
50
52
  headers = {
51
53
  item[0].decode().lower(): item[1].decode() for item in self.scope['headers']
@@ -91,7 +93,8 @@ class FleetConsumer(AsyncWebsocketConsumer):
91
93
  'name': headers.get('colonel-name'),
92
94
  'type': headers['colonel-type'],
93
95
  'firmware_version': headers['firmware-version'],
94
- 'last_seen': timezone.now()
96
+ 'last_seen': timezone.now(),
97
+ 'enabled': True
95
98
  }
96
99
  with transaction.atomic():
97
100
  colonel, new = Colonel.objects.get_or_create(
@@ -99,10 +102,10 @@ class FleetConsumer(AsyncWebsocketConsumer):
99
102
  )
100
103
  if not new:
101
104
  for key, val in defaults.items():
105
+ if key in ('new', ):
106
+ continue
102
107
  setattr(colonel, key, val)
103
- if new:
104
- colonel.enabled = True
105
- colonel.save()
108
+ colonel.save()
106
109
 
107
110
  return colonel, new
108
111
 
@@ -113,7 +116,6 @@ class FleetConsumer(AsyncWebsocketConsumer):
113
116
  print(f"Colonel {self.colonel} connected!")
114
117
  if not self.colonel.enabled:
115
118
  print("Colonel %s drop, it's not enabled!" % str(self.colonel))
116
- await self.accept()
117
119
  return await self.close()
118
120
 
119
121
  if headers.get('instance-uid') != self.colonel.instance.uid \
@@ -123,8 +125,6 @@ class FleetConsumer(AsyncWebsocketConsumer):
123
125
 
124
126
  self.connected = True
125
127
 
126
- await self.accept()
127
-
128
128
  await self.log_colonel_connected()
129
129
 
130
130
 
@@ -370,18 +370,19 @@ class FleetConsumer(AsyncWebsocketConsumer):
370
370
  )(id=id)
371
371
 
372
372
  if 'val' in data:
373
- def receive_val(val):
373
+ def receive_val(data):
374
374
  if data.get('actor'):
375
375
  fingerprint = Fingerprint.objects.filter(
376
376
  value=f"ttlock-{component.id}-{data.get('actor')}",
377
377
  ).first()
378
378
  component.change_init_fingerprint = fingerprint
379
379
  component.controller._receive_from_device(
380
- val, bool(data.get('alive'))
380
+ data['val'], bool(data.get('alive')),
381
+ data.get('battery_level')
381
382
  )
382
383
  await sync_to_async(
383
384
  receive_val, thread_sensitive=True
384
- )(data['val'])
385
+ )(data)
385
386
 
386
387
  if 'options' in data:
387
388
  def receive_options(val):
simo/users/middleware.py CHANGED
@@ -11,9 +11,8 @@ import threading
11
11
 
12
12
  # We use daphne for asgi, which seems to be working fine for what we have already
13
13
  # observed. However, this is a good candidate for reworking it in to something
14
- # more rboust.
14
+ # more robust.
15
15
 
16
- # TODO: rework this in to something more roboust
17
16
 
18
17
  _thread_locals = threading.local()
19
18
 
@@ -39,7 +38,6 @@ class IntroduceUser:
39
38
  self.get_response = get_response
40
39
 
41
40
  def __call__(self, request):
42
- response = self.get_response(request)
43
41
  if request.user.is_authenticated:
44
42
  introduce(request.user)
45
- return response
43
+ return self.get_response(request)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: Smart Home on Steroids!
5
5
  Author-email: Simanas Venčkauskas <simanas@simo.io>
6
6
  Project-URL: Homepage, https://simo.io
@@ -43,4 +43,5 @@ Requires-Dist: ansi2html ==1.7.0
43
43
  Requires-Dist: slugify ==0.0.1
44
44
  Requires-Dist: django-countries ==7.5.1
45
45
  Requires-Dist: librosa ==0.10.1
46
+ Requires-Dist: daphne ==4.1.0
46
47
 
@@ -20,21 +20,21 @@ simo/__pycache__/wsgi.cpython-38.pyc,sha256=Wt9kKkH2Sg5LRL4NrVQQDYPIoDyTvnXwm6jZ
20
20
  simo/_hub_template/hub/asgi.py,sha256=ElN_fdeSkf0Ysa7pS9rJVmZ1HmLhFxb8jFaMLqe1220,126
21
21
  simo/_hub_template/hub/celeryc.py,sha256=3ksDXftIZKJ4Cq9WNKJERdZdQlDEnjTQXycweRFmsSQ,27
22
22
  simo/_hub_template/hub/manage.py,sha256=PNNlw3EVeIJDgkG0l-klqoxsKWfTYWG9jzRG0upmAaI,620
23
- simo/_hub_template/hub/nginx.conf,sha256=k7wH2Z57q6kZCRWqYMxMO6_Dm7ThhqkO7Qz-rdvfz3E,2008
23
+ simo/_hub_template/hub/nginx.conf,sha256=MOJljsz_symwQF_L7ubp2ZnhkE7BrvkzIxZPtd1sWw0,2000
24
24
  simo/_hub_template/hub/settings.py,sha256=4QhvhbtLRxHvAntwqG_qeAAtpDUqKvN4jzw9u3vqff8,361
25
25
  simo/_hub_template/hub/supervisor.conf,sha256=IY3fdK0fDD2eAothB0n54xhjQj8LYoXIR96-Adda5Z8,1353
26
26
  simo/_hub_template/hub/urls.py,sha256=Ydm-1BkYAzWeEF-MKSDIFf-7aE4qNLPm48-SA51XgJQ,25
27
27
  simo/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  simo/core/admin.py,sha256=SXZlKI2aiEscDS12qXdkxDa30GNkFsgnJMT711S1wuw,17525
29
- simo/core/api.py,sha256=3uUaWOPD-wKrLktJqEg5J3eSeDLNQkZRRQAqQnMvlI4,23633
30
- simo/core/api_auth.py,sha256=2MRmCid_Fy67chKiJEt6_UaJZmb1PDF8KdbBlkA7YgU,1139
29
+ simo/core/api.py,sha256=D2uX25Do7UkKaYNNY5ZIMtuet8r-_XgoEzK9324smkw,23695
30
+ simo/core/api_auth.py,sha256=_3hG4e1eLKrcRnSAOB_xTL6cwtOJ2_7JS7GZU_iqTgA,1251
31
31
  simo/core/api_meta.py,sha256=li4KLFl6xTYOoD8pgS8PYcjqTZlzhXI0reAkt06PZFA,3404
32
32
  simo/core/app_widgets.py,sha256=EEQOto3fGR0syDqpJE38tQrx8DoTTyg26nF5kYzHY38,2018
33
33
  simo/core/auto_urls.py,sha256=0gu-IL7PHobrmKW6ksffiOkAYu-aIorykWdxRNtwGYo,1194
34
34
  simo/core/autocomplete_views.py,sha256=JT5LA2_Wtr60XYSAIqaXFKFYPjrmkEf6yunXD9y2zco,4022
35
35
  simo/core/base_types.py,sha256=yqbIZqBksrAkEuHRbt6iExwPDDy0K5II2NzRCkmOvMU,589
36
36
  simo/core/context.py,sha256=98PXAMie43faRVBFkOG22uNpvGRNprcGhzjBFkrxaRY,1367
37
- simo/core/controllers.py,sha256=7M28j0I2Eh-Q7jIXZ7FMkNQoA7xluu67NSXhJXaW4gs,27018
37
+ simo/core/controllers.py,sha256=paeZU6Ky2LgRTwj9nFqrgfeJ4kxWPcl95WDTf6P7jOo,27200
38
38
  simo/core/dynamic_settings.py,sha256=U2WNL96JzVXdZh0EqMPWrxqO6BaRR2Eo5KTDqz7MC4o,1943
39
39
  simo/core/events.py,sha256=LvtonJGNyCb6HLozs4EG0WZItnDwNdtnGQ4vTcnKvUs,4438
40
40
  simo/core/filters.py,sha256=ghtOZcrwNAkIyF5_G9Sn73NkiI71mXv0NhwCk4IyMIM,411
@@ -10125,13 +10125,13 @@ simo/fleet/api.py,sha256=Hxn84xI-Q77HxjINgRbjSJQOv9jii4OL20LxK0VSrS8,2499
10125
10125
  simo/fleet/auto_urls.py,sha256=gAXTWUvsWkQHRdZGM_W_5iJBEsM4lY063kIx3f5LUqs,578
10126
10126
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10127
10127
  simo/fleet/controllers.py,sha256=N8Qzdp2RPFrpZ_l9O4u8VjHWoY_WTWGg76s3V3oJqEs,13999
10128
- simo/fleet/forms.py,sha256=UGj1mK2Zbl2LRlvLtEDObeGfC2wcuHleRbePo1_Vx6I,34972
10128
+ simo/fleet/forms.py,sha256=HpvcdFyMl9dLNx1sEOkAkXOkYht6ku2HwWWga-PJzZQ,35067
10129
10129
  simo/fleet/gateways.py,sha256=xFsmF_SXYXK_kMJOCHkiInPJ_0VcPWz-kJDoMup2lT8,1576
10130
10130
  simo/fleet/managers.py,sha256=kpfvvfdH4LDxddIBDpdAb5gsVk8Gb0-L9biFcj9OFPs,807
10131
- simo/fleet/models.py,sha256=Ro0ZkYB3a7ZhczVQOxjAobCRECIdN0Nj0yb5EBybvW0,12809
10131
+ simo/fleet/models.py,sha256=O0lsXRmTgPyOhpcwWeJ-2GHTNe2uFhiJy4FTW9Ljz-c,11830
10132
10132
  simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
10133
10133
  simo/fleet/serializers.py,sha256=zEpXAXxjk4Rf1JhlNnLTrs20qJggqjvIySbeHVo4Tt4,1505
10134
- simo/fleet/socket_consumers.py,sha256=o8yr27AYxKFStQGyXZrk7PP1P2fUgSjsWp76DojWqbM,19415
10134
+ simo/fleet/socket_consumers.py,sha256=xNeR1IuaBTiHO2GEXwB1_4CJ29uMlqBycIUdxGT96E8,19578
10135
10135
  simo/fleet/utils.py,sha256=D0EGFbDmW8zyhyxf5ozGtRpo4Sy5Ov6ZixukBK_e2Do,3462
10136
10136
  simo/fleet/views.py,sha256=PbdZpsM_7-oyKzuDX1A5WULNABA1_B7ISF70UJX97FE,1662
10137
10137
  simo/fleet/__pycache__/__init__.cpython-38.pyc,sha256=pIZE7EL6-cuJ3pQtaSwjKLrKLsTYelp1k9sRhXKLh6s,159
@@ -10276,7 +10276,7 @@ simo/users/api.py,sha256=xJCCj75eQXdaYfiCxxG_rMDKzEZuYuCadOhOutqX2YY,9053
10276
10276
  simo/users/auth_backends.py,sha256=I5pnaTa20-Lxfw_dFG8471xDITb0_fQl1PVhJalp5vU,3992
10277
10277
  simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
10278
10278
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10279
- simo/users/middleware.py,sha256=9epN8xDcnYAMoEjAeJGg4W9e54szTgh48LKz3rlywFI,1287
10279
+ simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
10280
10280
  simo/users/models.py,sha256=f59mkQBpq_fFLDUa-44b1qWleB-TvGdC1M0G67huJMg,18498
10281
10281
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10282
10282
  simo/users/serializers.py,sha256=yrWghK7ONxfzkjO3LbDLK1WPxsPBMYUegdm29qovjjo,2486
@@ -10343,8 +10343,8 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10343
10343
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10344
10344
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10345
10345
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10346
- simo-2.0.3.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10347
- simo-2.0.3.dist-info/METADATA,sha256=kIgoVnqVIeZ9Paw4f7G6PA41Nwe3dafpPmpEbRV5JU4,1669
10348
- simo-2.0.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10349
- simo-2.0.3.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10350
- simo-2.0.3.dist-info/RECORD,,
10346
+ simo-2.0.5.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10347
+ simo-2.0.5.dist-info/METADATA,sha256=aQw7niHw3pcQrYlEkzWz-SoLhr68a4It838k65sh08Q,1699
10348
+ simo-2.0.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
10349
+ simo-2.0.5.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10350
+ simo-2.0.5.dist-info/RECORD,,
File without changes