simo 2.5.25__py3-none-any.whl → 2.5.26__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/middleware.py CHANGED
@@ -25,6 +25,12 @@ def introduce_instance(instance, request=None):
25
25
  request.instance = instance
26
26
 
27
27
 
28
+ def drop_current_instance(request=None):
29
+ if request and 'instance_id' in request.session:
30
+ request.session.pop('instance_id')
31
+ _thread_locals.instance = None
32
+
33
+
28
34
  def get_current_instance(request=None):
29
35
  from simo.core.models import Instance
30
36
  if request and request.session.get('instance_id'):
simo/fleet/forms.py CHANGED
@@ -1175,6 +1175,11 @@ class BlindsConfigForm(ColonelComponentForm):
1175
1175
  "to go from fully closed to the start of open movement. <br>"
1176
1176
  "Usually it's in between of 1 - 3 seconds."
1177
1177
  )
1178
+ retain_angle = forms.BooleanField(
1179
+ required=False, initial=True,
1180
+ help_text="Retain blinds angle after adjusting it's "
1181
+ "position using physical buttons."
1182
+ )
1178
1183
  control_mode = forms.ChoiceField(
1179
1184
  label="App control mode", required=True, choices=(
1180
1185
  ('click', "Click"), ('hold', "Hold"), ('slide', "Slide")
@@ -1186,6 +1191,10 @@ class BlindsConfigForm(ColonelComponentForm):
1186
1191
  )
1187
1192
  )
1188
1193
 
1194
+ def __init__(self, *args, **kwargs):
1195
+ self.basic_fields.append('retain_angle')
1196
+ return super().__init__(*args, **kwargs)
1197
+
1189
1198
  def clean(self):
1190
1199
  super().clean()
1191
1200
 
simo/fleet/models.py CHANGED
@@ -275,7 +275,7 @@ def after_colonel_save(sender, instance, created, *args, **kwargs):
275
275
  if instance.type == 'game-changer':
276
276
  # occupy ports immediately
277
277
  Interface.objects.create(colonel=instance, no=1, type='i2c')
278
- Interface.objects.create(colonel=instance, no=2, type='dali')
278
+ Interface.objects.create(colonel=instance, no=2)
279
279
  elif instance.type == 'game-changer-mini':
280
280
  # only create interfaces, but do not ocuupy ports
281
281
  Interface.objects.create(colonel=instance, no=1)
simo/generic/gateways.py CHANGED
@@ -12,7 +12,7 @@ from django.db import connection as db_connection
12
12
  from django.db.models import Q
13
13
  import paho.mqtt.client as mqtt
14
14
  from simo.core.models import Component
15
- from simo.core.middleware import introduce_instance
15
+ from simo.core.middleware import introduce_instance, drop_current_instance
16
16
  from simo.core.gateways import BaseObjectCommandsGatewayHandler
17
17
  from simo.core.forms import BaseGatewayForm
18
18
  from simo.core.utils.logs import StreamToLogger
@@ -132,6 +132,7 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
132
132
 
133
133
  def watch_thermostats(self):
134
134
  from .controllers import Thermostat
135
+ drop_current_instance()
135
136
  for thermostat in Component.objects.filter(
136
137
  controller_uid=Thermostat.uid
137
138
  ):
@@ -141,15 +142,18 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
141
142
 
142
143
  def watch_alarm_clocks(self):
143
144
  from .controllers import AlarmClock
145
+ drop_current_instance()
144
146
  for alarm_clock in Component.objects.filter(
145
147
  controller_uid=AlarmClock.uid
146
148
  ):
149
+ introduce_instance(alarm_clock.zone.instance)
147
150
  tz = pytz.timezone(alarm_clock.zone.instance.timezone)
148
151
  timezone.activate(tz)
149
152
  alarm_clock.tick()
150
153
 
151
154
  def watch_scripts(self):
152
155
  # observe running scripts and drop the ones that are no longer alive
156
+ drop_current_instance()
153
157
  dead_processes = []
154
158
  for id, process in self.running_scripts.items():
155
159
  if process.is_alive():
@@ -183,8 +187,10 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
183
187
  self.start_script(script)
184
188
 
185
189
  def watch_watering(self):
190
+ drop_current_instance()
186
191
  from .controllers import Watering
187
192
  for watering in Component.objects.filter(controller_uid=Watering.uid):
193
+ introduce_instance(watering.zone.instance)
188
194
  tz = pytz.timezone(watering.zone.instance.timezone)
189
195
  timezone.activate(tz)
190
196
  if watering.value['status'] == 'running_program':
@@ -195,6 +201,7 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
195
201
  watering.controller._perform_schedule()
196
202
 
197
203
  def run(self, exit):
204
+ drop_current_instance()
198
205
  self.exit = exit
199
206
  self.logger = get_gw_logger(self.gateway_instance.id)
200
207
  for task, period in self.periodic_tasks:
@@ -261,9 +268,11 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
261
268
  Script, AlarmGroup
262
269
  )
263
270
  payload = json.loads(msg.payload)
271
+ drop_current_instance()
264
272
  component = get_event_obj(payload, Component)
265
273
  if not component:
266
274
  return
275
+ introduce_instance(component.zone.instance)
267
276
  try:
268
277
  if isinstance(component.controller, Script):
269
278
  if payload.get('set_val') == 'start':
@@ -373,6 +382,7 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
373
382
 
374
383
  def watch_alarm_events(self):
375
384
  from .controllers import AlarmGroup
385
+ drop_current_instance()
376
386
  for alarm in Component.objects.filter(
377
387
  controller_uid=AlarmGroup.uid, value='breached',
378
388
  meta__breach_start__gt=0
@@ -393,6 +403,7 @@ class GenericGatewayHandler(BaseObjectCommandsGatewayHandler):
393
403
  alarm.save(update_fields=['meta'])
394
404
 
395
405
  def watch_timers(self):
406
+ drop_current_instance()
396
407
  for component in Component.objects.filter(
397
408
  meta__timer_to__gt=0
398
409
  ).filter(meta__timer_to__lt=time.time()):
@@ -99,13 +99,17 @@ class SSOBackend(ModelBackend):
99
99
  user=user, instance=invitation.instance,
100
100
  defaults={'role': invitation.role}
101
101
  )
102
- user.is_active = True
102
+ if not user.is_active:
103
+ user.is_active = True
104
+ user.save()
103
105
 
104
106
  if not user.is_active:
105
107
  return
106
108
 
107
109
  if user_data.get('name'):
108
- user.name = user_data['name']
110
+ if user_data['name'] != user.name:
111
+ user.name = user_data['name']
112
+ user.save()
109
113
  if user_data.get('avatar_url') \
110
114
  and user.avatar_url != user_data.get('avatar_url'):
111
115
  user.avatar_url = user_data.get('avatar_url')
@@ -113,7 +117,5 @@ class SSOBackend(ModelBackend):
113
117
  user.avatar.save(
114
118
  os.path.basename(user.avatar_url), io.BytesIO(resp.content)
115
119
  )
116
- if user.get_dirty_fields():
117
- user.save()
118
120
 
119
121
  return user
simo/users/models.py CHANGED
@@ -154,7 +154,10 @@ def post_instance_user_save(sender, instance, created, **kwargs):
154
154
  dynamic_settings['core__needs_mqtt_acls_rebuild'] = True
155
155
 
156
156
 
157
- class User(DirtyFieldsMixin, AbstractBaseUser, SimoAdminMixin):
157
+ # DirtyFieldsMixin does not work with AbstractBaseUser model!!!
158
+ # goes in to RecursionError: maximum recursion depth exceeded
159
+ # when saving, so do not ever use it!!!!
160
+ class User(AbstractBaseUser, SimoAdminMixin):
158
161
  name = models.CharField(_('name'), max_length=150)
159
162
  email = models.EmailField(_('email address'), unique=True)
160
163
  avatar = ThumbnailerImageField(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: simo
3
- Version: 2.5.25
3
+ Version: 2.5.26
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
@@ -51,7 +51,7 @@ simo/core/forms.py,sha256=O40apPH7a4qX4WdCc10A1aoAaGWOpKqmjB8d-OhEKCo,21523
51
51
  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
- simo/core/middleware.py,sha256=hExD7Vmw7eitk0vAjOwKzkwrtuw8YxpflF92j_CA2YY,3193
54
+ simo/core/middleware.py,sha256=j_nZQPwT21xuVP2glNTbLm4LE-dvqxroeEcl8Oy3DzA,3367
55
55
  simo/core/models.py,sha256=DXJXTtNdpn9yC4VArHp0yrhpRb7vGpwH2c-JvqLE56M,22784
56
56
  simo/core/permissions.py,sha256=INQPrUAIM3WXCvd7e6cmYytKaak8fMEn7VooX-fIds0,3002
57
57
  simo/core/routing.py,sha256=X1_IHxyA-_Q7hw1udDoviVP4_FSBDl8GYETTC2zWTbY,499
@@ -10224,10 +10224,10 @@ simo/fleet/auto_urls.py,sha256=UX66eR2ykMqFgfIllW-RTdjup5-FieCWl_BVm3CcXKg,702
10224
10224
  simo/fleet/base_types.py,sha256=wL9RVkHr0gA7HI1wZq0pruGEIgvQqpfnCL4cC3ywsvw,102
10225
10225
  simo/fleet/ble.py,sha256=eHA_9ABjbmH1vUVCv9hiPXQL2GZZSEVwfO0xyI1S0nI,1081
10226
10226
  simo/fleet/controllers.py,sha256=fjri1GtCnflkkDpNqhTwy6i9CK6RDEB0Q_BtADzcG8E,29156
10227
- simo/fleet/forms.py,sha256=LbYphCtfpSxK3GwzSrcbMkB_spcspsf5FzYQFE9n-Q4,62614
10227
+ simo/fleet/forms.py,sha256=dNyM0hAKR93DPeKs6NJnE42prAeCR4MoXjkv5mGeQ4g,62952
10228
10228
  simo/fleet/gateways.py,sha256=lKEJW0MgaOEiNnijH50DNSVChvaUT3TA3UurcI57P8k,5677
10229
10229
  simo/fleet/managers.py,sha256=ZNeHFSkF5kzsl9E1DCBevOW6kXJlD6kw0LU4B-JMOG8,828
10230
- simo/fleet/models.py,sha256=xAffeAh5hf8NC94B66ZqmYoF7qDN53wEQ1xE2E9D8Xc,17524
10230
+ simo/fleet/models.py,sha256=zPplx_v64nfKBmb-nCb74aCVtEeY3m3SjEy-VhbnydU,17511
10231
10231
  simo/fleet/routing.py,sha256=cofGsVWXMfPDwsJ6HM88xxtRxHwERhJ48Xyxc8mxg5o,149
10232
10232
  simo/fleet/serializers.py,sha256=X2M0DFKVaxM6JFGDsdg3S2nJlLIcBvbujidZdfxD88w,2169
10233
10233
  simo/fleet/socket_consumers.py,sha256=nfwMAzHHDWrvmwOIfPJqYHgr2fF-OJ_l6gWOnljyFWI,18434
@@ -10342,7 +10342,7 @@ simo/generic/app_widgets.py,sha256=TPRLj4hri2hBuY6mrdwBiv-01z2hDxZmsup-GDD9LrM,9
10342
10342
  simo/generic/base_types.py,sha256=u3SlfpNYaCwkVBwomWgso4ODzL71ay9MhiAW-bxgnDU,341
10343
10343
  simo/generic/controllers.py,sha256=i-xKQ5PrNKwCuO0dFaHHUaD5rF9lDnq18ziVSNBENao,50134
10344
10344
  simo/generic/forms.py,sha256=H841-wbWltnZ2-RXQEM1G8H4kfOcl88Qhg7bxE4VCiQ,28993
10345
- simo/generic/gateways.py,sha256=sMedpxIfpxqTx746DdhsIu-pzTrqduOSIb7i7XDX9GU,15339
10345
+ simo/generic/gateways.py,sha256=MxPQzgEnnXSG-t6rErHZQJACFWegCWGaME640UIGrA8,15783
10346
10346
  simo/generic/models.py,sha256=Adq7ipWK-renxJlNW-SZnAq2oGEOwKx8EdUWaKnfcVQ,7597
10347
10347
  simo/generic/routing.py,sha256=elQVZmgnPiieEuti4sJ7zITk1hlRxpgbotcutJJgC60,228
10348
10348
  simo/generic/socket_consumers.py,sha256=K2OjphIhKJH48BvfFfoCOyCQZ1NmXb_phs6y1IP-qaQ,1757
@@ -10445,12 +10445,12 @@ simo/users/__init__.py,sha256=6a7uBpCWB_DR7p54rbHusc0xvi1qfT1ZCCQGb6TiBh8,52
10445
10445
  simo/users/admin.py,sha256=9P0iIGAep2R1AUvZnROsRULbxwCYK9pCfSJ2X4aLLBg,6965
10446
10446
  simo/users/api.py,sha256=xe__HFxzOaKgrh75PFpP4nkSs5DvmJp8QvMDNhP5kLU,12127
10447
10447
  simo/users/apps.py,sha256=cq0A8-U1HALEwev0TicgFhr4CAu7Icz8rwq0HfOaL4E,207
10448
- simo/users/auth_backends.py,sha256=EErYrGti3TIlYH9Bxj0UFs5EKsbYMV4FP4wGfpdHtts,4165
10448
+ simo/users/auth_backends.py,sha256=KIw2AdjCUKfm_7Lql6aC4qdE6JznP0ECIMA5MVMLeiM,4251
10449
10449
  simo/users/auto_urls.py,sha256=lcJvteBsbHQMJieZpDz-63tDYejLApqsW3CUnDakd7k,272
10450
10450
  simo/users/dynamic_settings.py,sha256=sEIsi4yJw3kH46Jq_aOkSuK7QTfQACGUE-lkyBogCaM,570
10451
10451
  simo/users/managers.py,sha256=OHgEP85MBtdkdYxdstBd8RavTBT8F_2WyDxUJ9aCqqM,246
10452
10452
  simo/users/middleware.py,sha256=GMCrnWSc_2qCleyQIkfQGdL-pU-UTEcSg1wPvIKZ9uk,1210
10453
- simo/users/models.py,sha256=KcIanqB8xvgvTO_jAUJpoN6JSRJha_DhIDSs4lniFXA,19402
10453
+ simo/users/models.py,sha256=Ms5YiU_N1rDSxWMYErO1RnBiK7Jo8Ww_raYJZ5p4yL0,19551
10454
10454
  simo/users/permissions.py,sha256=IwtYS8yQdupWbYKR9VimSRDV3qCJ2jXP57Lyjpb2EQM,242
10455
10455
  simo/users/serializers.py,sha256=zzw1KONTnaTNBaU0r4rNVxJ827KzD6Z5LuQt27ZsQ98,2516
10456
10456
  simo/users/sso_urls.py,sha256=gQOaPvGMYFD0NCVSwyoWO-mTEHe5j9sbzV_RK7kdvp0,251
@@ -10561,9 +10561,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
10561
10561
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10562
10562
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10563
10563
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10564
- simo-2.5.25.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10565
- simo-2.5.25.dist-info/METADATA,sha256=0QbwBkQyX8aCdHsmCEsHZAP2gqvrBugk80H1VV06kRI,1924
10566
- simo-2.5.25.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10567
- simo-2.5.25.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10568
- simo-2.5.25.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10569
- simo-2.5.25.dist-info/RECORD,,
10564
+ simo-2.5.26.dist-info/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
10565
+ simo-2.5.26.dist-info/METADATA,sha256=CE-CKVFUAiMRRc6FxPMUlSdJqpVyGbVc4L1Y6rB7Mx4,1924
10566
+ simo-2.5.26.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
10567
+ simo-2.5.26.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
10568
+ simo-2.5.26.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
10569
+ simo-2.5.26.dist-info/RECORD,,
File without changes