simo 2.10.9__py3-none-any.whl → 2.11.1__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/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/__pycache__/asgi.cpython-312.pyc +0 -0
- simo/__pycache__/celeryc.cpython-312.pyc +0 -0
- simo/__pycache__/conf.cpython-312.pyc +0 -0
- simo/__pycache__/settings.cpython-312.pyc +0 -0
- simo/__pycache__/urls.cpython-312.pyc +0 -0
- simo/automation/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/automation/__pycache__/app_widgets.cpython-312.pyc +0 -0
- simo/automation/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/automation/__pycache__/forms.cpython-312.pyc +0 -0
- simo/automation/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/automation/__pycache__/helpers.cpython-312.pyc +0 -0
- simo/automation/__pycache__/models.cpython-312.pyc +0 -0
- simo/automation/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/automation/__pycache__/state.cpython-312.pyc +0 -0
- simo/automation/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/automation/migrations/__pycache__/0002_update_helpers_in_scripts.cpython-312.pyc +0 -0
- simo/automation/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/automation/templates/automations/__pycache__/auto_away.cpython-312.pyc +0 -0
- simo/automation/templates/automations/__pycache__/auto_state_script.cpython-312.pyc +0 -0
- simo/automation/templates/automations/__pycache__/phones_sleep_script.cpython-312.pyc +0 -0
- simo/backups/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/backups/__pycache__/admin.cpython-312.pyc +0 -0
- simo/backups/__pycache__/dynamic_settings.cpython-312.pyc +0 -0
- simo/backups/__pycache__/models.cpython-312.pyc +0 -0
- simo/backups/__pycache__/tasks.cpython-312.pyc +0 -0
- simo/backups/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/backups/migrations/__pycache__/0002_backuplog_backup_level_backup_size.cpython-312.pyc +0 -0
- simo/backups/migrations/__pycache__/0003_alter_backuplog_options_alter_backup_size.cpython-312.pyc +0 -0
- simo/backups/migrations/__pycache__/0004_alter_backup_options_alter_backuplog_options_and_more.cpython-312.pyc +0 -0
- simo/backups/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/backups/rescue.img.xz +0 -0
- simo/backups/tasks.py +361 -17
- simo/core/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/__pycache__/admin.cpython-312.pyc +0 -0
- simo/core/__pycache__/api.cpython-312.pyc +0 -0
- simo/core/__pycache__/api_auth.cpython-312.pyc +0 -0
- simo/core/__pycache__/api_meta.cpython-312.pyc +0 -0
- simo/core/__pycache__/app_widgets.cpython-312.pyc +0 -0
- simo/core/__pycache__/apps.cpython-312.pyc +0 -0
- simo/core/__pycache__/auto_urls.cpython-312.pyc +0 -0
- simo/core/__pycache__/autocomplete_views.cpython-312.pyc +0 -0
- simo/core/__pycache__/base_types.cpython-312.pyc +0 -0
- simo/core/__pycache__/context.cpython-312.pyc +0 -0
- simo/core/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/core/__pycache__/dynamic_settings.cpython-312.pyc +0 -0
- simo/core/__pycache__/events.cpython-312.pyc +0 -0
- simo/core/__pycache__/filters.cpython-312.pyc +0 -0
- simo/core/__pycache__/form_fields.cpython-312.pyc +0 -0
- simo/core/__pycache__/forms.cpython-312.pyc +0 -0
- simo/core/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/core/__pycache__/loggers.cpython-312.pyc +0 -0
- simo/core/__pycache__/managers.cpython-312.pyc +0 -0
- simo/core/__pycache__/middleware.cpython-312.pyc +0 -0
- simo/core/__pycache__/models.cpython-312.pyc +0 -0
- simo/core/__pycache__/permissions.cpython-312.pyc +0 -0
- simo/core/__pycache__/routing.cpython-312.pyc +0 -0
- simo/core/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/core/__pycache__/signal_receivers.cpython-312.pyc +0 -0
- simo/core/__pycache__/socket_consumers.cpython-312.pyc +0 -0
- simo/core/__pycache__/storage.cpython-312.pyc +0 -0
- simo/core/__pycache__/tasks.cpython-312.pyc +0 -0
- simo/core/__pycache__/todos.cpython-312.pyc +0 -0
- simo/core/__pycache__/types.cpython-312.pyc +0 -0
- simo/core/__pycache__/views.cpython-312.pyc +0 -0
- simo/core/__pycache__/widgets.cpython-312.pyc +0 -0
- simo/core/controllers.py +6 -3
- simo/core/db_backend/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/db_backend/__pycache__/base.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/mixins.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/models.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/parsers.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/renderers.cpython-312.pyc +0 -0
- simo/core/drf_braces/__pycache__/utils.cpython-312.pyc +0 -0
- simo/core/drf_braces/fields/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/fields/__pycache__/_fields.cpython-312.pyc +0 -0
- simo/core/drf_braces/fields/__pycache__/custom.cpython-312.pyc +0 -0
- simo/core/drf_braces/fields/__pycache__/mixins.cpython-312.pyc +0 -0
- simo/core/drf_braces/fields/__pycache__/modified.cpython-312.pyc +0 -0
- simo/core/drf_braces/forms/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/forms/__pycache__/fields.cpython-312.pyc +0 -0
- simo/core/drf_braces/forms/__pycache__/serializer_form.cpython-312.pyc +0 -0
- simo/core/drf_braces/serializers/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/serializers/__pycache__/enforce_validation_serializer.cpython-312.pyc +0 -0
- simo/core/drf_braces/serializers/__pycache__/form_serializer.cpython-312.pyc +0 -0
- simo/core/drf_braces/serializers/__pycache__/swapping.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/__pycache__/test_mixins.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/__pycache__/test_parsers.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/__pycache__/test_renderers.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/__pycache__/test_utils.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/fields/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/fields/__pycache__/test_custom.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/fields/__pycache__/test_fields.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/fields/__pycache__/test_mixins.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/fields/__pycache__/test_modified.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/forms/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/forms/__pycache__/test_fields.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/forms/__pycache__/test_serializer_form.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/serializers/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/serializers/__pycache__/test_enforce_validation_serializer.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/serializers/__pycache__/test_form_serializer.cpython-312.pyc +0 -0
- simo/core/drf_braces/tests/serializers/__pycache__/test_swapping.cpython-312.pyc +0 -0
- simo/core/management/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/management/__pycache__/update.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/asgi.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/celeryc.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/manage.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/settings.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/urls.cpython-312.pyc +0 -0
- simo/core/management/_hub_template/hub/__pycache__/wsgi.cpython-312.pyc +0 -0
- simo/core/management/commands/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/management/commands/__pycache__/gateways_manager.cpython-312.pyc +0 -0
- simo/core/management/commands/__pycache__/on_http_start.cpython-312.pyc +0 -0
- simo/core/management/commands/__pycache__/run_gateway.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0002_load_icons.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0003_create_default_zones_and_categories.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0004_create_generic.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0005_component_subcomponents.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0006_alter_component_subcomponents.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0007_component_change_init_to.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0008_alter_component_change_init_to.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0009_auto_20220707_1404.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0010_historyaggregate.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0011_component_last_change.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0012_instance.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0013_auto_20231003_0754.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0014_zone_instance.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0015_auto_20231004_1113.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0016_auto_20231004_1113.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0017_auto_20231004_1313.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0018_auto_20231005_0622.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0019_alter_gateway_type.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0020_component_meta.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0021_auto_20231020_1041.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0022_auto_20231221_0735.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0023_auto_20231229_1352.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0024_alter_instance_device_report_history_days.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0025_auto_20240122_1321.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0026_category_instance.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0027_remove_component_tags.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0028_rename_subcomponents_component_slaves.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0029_auto_20240229_1331.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0030_alter_instance_timezone.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0031_auto_20240429_1231.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0032_auto_20240506_0834.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0033_auto_20240509_0821.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0034_component_error_msg.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0035_remove_instance_share_location.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0036_auto_20240521_0823.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0037_auto_20240606_1057.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0038_remove_instance_cover_image_and_more.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0039_instance_is_active_alter_instance_timezone.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0040_alter_instance_name.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0041_alter_instance_slug.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0042_alter_instance_timezone.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0043_alter_category_instance_alter_instance_timezone_and_more.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0044_alter_gateway_type.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0045_alter_instance_device_report_history_days_and_more.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0046_component_value_translation_alter_gateway_type.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0047_alter_component_value_translation.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0048_publicfile_privatefile.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0049_alter_gateway_type.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/0050_componenthistory_alive.cpython-312.pyc +0 -0
- simo/core/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/templates/core/__pycache__/value_translation.cpython-312.pyc +0 -0
- simo/core/templatetags/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/templatetags/__pycache__/components_list.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/admin.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/api.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/cache.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/config_values.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/converters.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/easing.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/form_fields.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/form_widgets.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/formsets.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/helpers.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/json.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/logs.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/mixins.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/model_helpers.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/operations.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/relay.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/serialization.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/type_constants.cpython-312.pyc +0 -0
- simo/core/utils/__pycache__/validators.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/admin.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/api.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/apps.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/auto_urls.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/base_types.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/ble.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/custom_dali_operations.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/forms.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/managers.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/models.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/routing.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/socket_consumers.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/tasks.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/utils.cpython-312.pyc +0 -0
- simo/fleet/__pycache__/views.cpython-312.pyc +0 -0
- simo/fleet/controllers.py +102 -47
- simo/fleet/custom_dali_operations.py +14 -2
- simo/fleet/forms.py +112 -101
- simo/fleet/migrations/0054_auto_20250507_1256.py +36 -0
- simo/fleet/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0002_auto_20220422_0743.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0003_auto_20220422_0752.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0004_auto_20220422_0818.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0005_auto_20220428_0900.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0006_rename_mac_colonel_uid.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0007_colonel_socket_connected.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0008_i2cinterface.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0009_i2cinterface_name.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0010_auto_20220602_0746.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0011_i2cinterface_freq.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0012_colonel_logs_stream.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0013_alter_colonel_last_seen.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0014_auto_20220614_0659.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0015_auto_20220614_0754.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0016_auto_20220704_0840.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0017_alter_colonel_secret.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0018_colonel_instance.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0019_auto_20231006_0749.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0020_instanceoptions.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0021_auto_20231006_0819.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0022_remove_colonel_secret.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0023_colonel_is_authorized.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0024_colonel_pwm_frequency.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0025_auto_20240130_1334.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0026_rename_i2cinterface_scl_pin_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0027_auto_20240306_0802.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0028_remove_i2cinterface_scl_pin_no_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0029_alter_i2cinterface_scl_pin_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0030_colonelpin_label_alter_colonel_type.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0031_alter_colonel_type.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0032_auto_20240415_0736.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0033_auto_20240415_0736.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0034_auto_20240418_0735.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0035_auto_20240514_0855.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0036_auto_20240605_0702.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0037_alter_colonelpin_options_alter_colonelpin_no_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0038_alter_colonel_type.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0039_auto_20241016_1047.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0040_alter_colonel_pwm_frequency.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0041_alter_colonel_instance_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0042_auto_20241120_1028.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0043_auto_20241203_0930.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0044_auto_20241210_0707.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0045_alter_colonel_type_customdalidevice.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0046_delete_customdalidevice.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0047_customdalidevice.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0048_remove_customdalidevice_colonel_and_more.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0049_alter_customdalidevice_interface.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0050_customdalidevice_uid.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0051_customdalidevice_components.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0052_colonelpin_interface.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0053_auto_20250507_0713.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/0054_auto_20250507_1256.cpython-312.pyc +0 -0
- simo/fleet/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/fleet/models.py +1 -1
- simo/generic/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/generic/__pycache__/app_widgets.cpython-312.pyc +0 -0
- simo/generic/__pycache__/base_types.cpython-312.pyc +0 -0
- simo/generic/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/generic/__pycache__/forms.cpython-312.pyc +0 -0
- simo/generic/__pycache__/gateways.cpython-312.pyc +0 -0
- simo/generic/__pycache__/models.cpython-312.pyc +0 -0
- simo/generic/__pycache__/routing.cpython-312.pyc +0 -0
- simo/generic/__pycache__/socket_consumers.cpython-312.pyc +0 -0
- simo/generic/__pycache__/tasks.cpython-312.pyc +0 -0
- simo/generic/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/generic/migrations/__pycache__/0002_auto_20241126_0726.cpython-312.pyc +0 -0
- simo/generic/migrations/__pycache__/0003_auto_20250409_1404.cpython-312.pyc +0 -0
- simo/generic/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/admin.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/api.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/app_widgets.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/auto_urls.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/base_types.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/controllers.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/forms.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/models.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/multimedia/__pycache__/views.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0002_sound_length.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0003_alter_sound_length.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0004_auto_20231023_1055.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0005_remove_sound_slug_sound_date_uploaded.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/0006_remove_sound_length_sound_duration.cpython-312.pyc +0 -0
- simo/multimedia/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/admin.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/api.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/models.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/notifications/__pycache__/utils.cpython-312.pyc +0 -0
- simo/notifications/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/notifications/migrations/__pycache__/0002_notification_instance.cpython-312.pyc +0 -0
- simo/notifications/migrations/__pycache__/0003_alter_notification_instance.cpython-312.pyc +0 -0
- simo/notifications/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/users/__pycache__/__init__.cpython-312.pyc +0 -0
- simo/users/__pycache__/admin.cpython-312.pyc +0 -0
- simo/users/__pycache__/api.cpython-312.pyc +0 -0
- simo/users/__pycache__/apps.cpython-312.pyc +0 -0
- simo/users/__pycache__/auth_backends.cpython-312.pyc +0 -0
- simo/users/__pycache__/auto_urls.cpython-312.pyc +0 -0
- simo/users/__pycache__/dynamic_settings.cpython-312.pyc +0 -0
- simo/users/__pycache__/managers.cpython-312.pyc +0 -0
- simo/users/__pycache__/middleware.cpython-312.pyc +0 -0
- simo/users/__pycache__/models.cpython-312.pyc +0 -0
- simo/users/__pycache__/permissions.cpython-312.pyc +0 -0
- simo/users/__pycache__/serializers.cpython-312.pyc +0 -0
- simo/users/__pycache__/sso_urls.cpython-312.pyc +0 -0
- simo/users/__pycache__/sso_views.cpython-312.pyc +0 -0
- simo/users/__pycache__/tasks.cpython-312.pyc +0 -0
- simo/users/__pycache__/utils.cpython-312.pyc +0 -0
- simo/users/__pycache__/views.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0002_componentpermission.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0003_create_roles_and_system_user.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0004_user_secret_key.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0005_permissionsrole_instance.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0006_auto_20231003_0850.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0007_auto_20231003_1228.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0008_auto_20231003_1229.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0009_remove_user_role.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0010_auto_20231004_1313.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0011_auto_20231004_1313.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0012_alter_userinstancerole_unique_together.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0013_remove_user_roles.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0014_user_roles.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0015_remove_user_at_home.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0016_auto_20231005_1050.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0017_auto_20231221_0735.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0018_user_is_god.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0019_auto_20231221_1155.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0020_rename_is_god_user_is_master.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0021_alter_permissionsrole_instance.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0022_userdevicereportlog_instance.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0023_auto_20240105_0719.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0024_fingerprint.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0025_rename_name_fingerprint_type_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0026_fingerprint_name.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0027_permissionsrole_can_manage_components.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0028_auto_20240506_1146.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0029_alter_instanceuser_instance.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0030_userdevice_users.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0031_auto_20240923_1115.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0032_remove_userdevice_user_alter_userdevice_users.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0033_alter_user_ssh_key.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0034_instanceuser_last_seen_location_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0035_instanceuser_last_seen_speed_kmh_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0036_instanceuser_phone_on_charge_user_phone_on_charge.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0037_rename_last_seen_location_datetime_instanceuser_last_seen_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0038_userdevicereportlog_at_home_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0039_auto_20241117_1039.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0040_userdevicereportlog_location_smoothed_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0041_userdevicereportlog_speed_kmh_received.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0042_remove_userdevicereportlog_location_smoothed_and_more.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0043_userdevicereportlog_avg_speed_kmh.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/0044_permissionsrole_is_person.cpython-312.pyc +0 -0
- simo/users/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/METADATA +1 -1
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/RECORD +379 -376
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/WHEEL +1 -1
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/entry_points.txt +0 -0
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/licenses/LICENSE.md +0 -0
- {simo-2.10.9.dist-info → simo-2.11.1.dist-info}/top_level.txt +0 -0
simo/fleet/controllers.py
CHANGED
|
@@ -10,20 +10,21 @@ from simo.core.controllers import (
|
|
|
10
10
|
Switch as BaseSwitch, Dimmer as BaseDimmer,
|
|
11
11
|
MultiSensor as BaseMultiSensor, RGBWLight as BaseRGBWLight,
|
|
12
12
|
Blinds as BaseBlinds, Gate as BaseGate,
|
|
13
|
+
Lock, ControllerBase, SingleSwitchWidget
|
|
13
14
|
)
|
|
14
15
|
from simo.core.app_widgets import NumericSensorWidget, AirQualityWidget
|
|
15
|
-
from simo.core.controllers import Lock, ControllerBase, SingleSwitchWidget
|
|
16
16
|
from simo.core.utils.helpers import heat_index
|
|
17
17
|
from simo.core.utils.serialization import (
|
|
18
18
|
serialize_form_data, deserialize_form_data
|
|
19
19
|
)
|
|
20
20
|
from simo.core.forms import BaseComponentForm
|
|
21
|
+
from simo.generic.controllers import StateSelect
|
|
21
22
|
from .models import Colonel, CustomDaliDevice
|
|
22
23
|
from .gateways import FleetGatewayHandler
|
|
23
24
|
from .forms import (
|
|
24
25
|
ColonelPinChoiceField,
|
|
25
26
|
ColonelBinarySensorConfigForm, ColonelButtonConfigForm,
|
|
26
|
-
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm,
|
|
27
|
+
ColonelSwitchConfigForm, ColonelPWMOutputConfigForm, DC10VConfigForm,
|
|
27
28
|
ColonelNumericSensorConfigForm, ColonelRGBLightConfigForm,
|
|
28
29
|
ColonelDHTSensorConfigForm, DS18B20SensorConfigForm,
|
|
29
30
|
BME680SensorConfigForm, MCP9808SensorConfigForm, ENS160SensorConfigForm,
|
|
@@ -37,7 +38,7 @@ from .forms import (
|
|
|
37
38
|
)
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
class
|
|
41
|
+
class FleetDeviceMixin:
|
|
41
42
|
|
|
42
43
|
def update_options(self, options):
|
|
43
44
|
GatewayObjectCommand(
|
|
@@ -91,11 +92,11 @@ class BasicSensorMixin:
|
|
|
91
92
|
self.component.config['pin_no'],
|
|
92
93
|
]
|
|
93
94
|
|
|
94
|
-
class BinarySensor(
|
|
95
|
+
class BinarySensor(FleetDeviceMixin, BasicSensorMixin, BaseBinarySensor):
|
|
95
96
|
config_form = ColonelBinarySensorConfigForm
|
|
96
97
|
|
|
97
98
|
|
|
98
|
-
class Button(
|
|
99
|
+
class Button(FleetDeviceMixin, BasicSensorMixin, BaseButton):
|
|
99
100
|
config_form = ColonelButtonConfigForm
|
|
100
101
|
|
|
101
102
|
|
|
@@ -110,12 +111,12 @@ class BurglarSmokeDetector(BinarySensor):
|
|
|
110
111
|
]
|
|
111
112
|
|
|
112
113
|
|
|
113
|
-
class DS18B20Sensor(
|
|
114
|
+
class DS18B20Sensor(FleetDeviceMixin, BasicSensorMixin, BaseNumericSensor):
|
|
114
115
|
config_form = DS18B20SensorConfigForm
|
|
115
116
|
name = "DS18B20 Temperature sensor"
|
|
116
117
|
|
|
117
118
|
|
|
118
|
-
class DHTSensor(
|
|
119
|
+
class DHTSensor(FleetDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
119
120
|
config_form = ColonelDHTSensorConfigForm
|
|
120
121
|
name = "DHT climate sensor"
|
|
121
122
|
app_widget = NumericSensorWidget
|
|
@@ -171,7 +172,7 @@ class BME680Sensor(DHTSensor):
|
|
|
171
172
|
|
|
172
173
|
|
|
173
174
|
|
|
174
|
-
class MCP9808TempSensor(
|
|
175
|
+
class MCP9808TempSensor(FleetDeviceMixin, BaseNumericSensor):
|
|
175
176
|
gateway_class = FleetGatewayHandler
|
|
176
177
|
config_form = MCP9808SensorConfigForm
|
|
177
178
|
name = "MCP9808 Temperature Sensor (I2C)"
|
|
@@ -196,7 +197,7 @@ class MCP9808TempSensor(FleeDeviceMixin, BaseNumericSensor):
|
|
|
196
197
|
return value
|
|
197
198
|
|
|
198
199
|
|
|
199
|
-
class ENS160AirQualitySensor(
|
|
200
|
+
class ENS160AirQualitySensor(FleetDeviceMixin, BaseMultiSensor):
|
|
200
201
|
gateway_class = FleetGatewayHandler
|
|
201
202
|
config_form = ENS160SensorConfigForm
|
|
202
203
|
name = "ENS160 Air Quality Sensor (I2C)"
|
|
@@ -257,7 +258,7 @@ class BasicOutputMixin:
|
|
|
257
258
|
).publish()
|
|
258
259
|
|
|
259
260
|
|
|
260
|
-
class Switch(
|
|
261
|
+
class Switch(FleetDeviceMixin, BasicOutputMixin, BaseSwitch):
|
|
261
262
|
config_form = ColonelSwitchConfigForm
|
|
262
263
|
|
|
263
264
|
def signal(self, pulses):
|
|
@@ -313,8 +314,8 @@ class FadeMixin:
|
|
|
313
314
|
).publish()
|
|
314
315
|
|
|
315
316
|
|
|
316
|
-
class PWMOutput(FadeMixin,
|
|
317
|
-
name = "Dimmer"
|
|
317
|
+
class PWMOutput(FadeMixin, FleetDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
318
|
+
name = "AC/DC Dimmer | PWM Driver"
|
|
318
319
|
config_form = ColonelPWMOutputConfigForm
|
|
319
320
|
|
|
320
321
|
def _prepare_for_send(self, value):
|
|
@@ -344,7 +345,7 @@ class PWMOutput(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
344
345
|
|
|
345
346
|
def _prepare_for_set(self, pwm_value):
|
|
346
347
|
conf = self.component.config
|
|
347
|
-
duty_max = 1023 -
|
|
348
|
+
duty_max = 1023 - conf.get('device_min', 0) * 0.01 * 1023
|
|
348
349
|
duty_min = 1023 - conf.get('device_max', 100) * 0.01 * 1023
|
|
349
350
|
|
|
350
351
|
if pwm_value > duty_max:
|
|
@@ -352,7 +353,7 @@ class PWMOutput(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
352
353
|
elif pwm_value < duty_min:
|
|
353
354
|
value = conf.get('min', 0)
|
|
354
355
|
else:
|
|
355
|
-
pwm_amplitude =duty_max - duty_min
|
|
356
|
+
pwm_amplitude = duty_max - duty_min
|
|
356
357
|
relative_value = (pwm_value - duty_min) / pwm_amplitude
|
|
357
358
|
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
358
359
|
value = conf.get('min', 0) + val_amplitude * relative_value
|
|
@@ -362,57 +363,71 @@ class PWMOutput(FadeMixin, FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
362
363
|
return round(value, 3)
|
|
363
364
|
|
|
364
365
|
|
|
365
|
-
class
|
|
366
|
-
name = "0 -
|
|
367
|
-
config_form =
|
|
368
|
-
default_value_units = '
|
|
366
|
+
class DC10VDriver(FadeMixin, FleetDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
367
|
+
name = "0 - 10V Driver"
|
|
368
|
+
config_form = DC10VConfigForm
|
|
369
|
+
default_value_units = '%'
|
|
369
370
|
|
|
370
371
|
def _prepare_for_send(self, value):
|
|
371
372
|
conf = self.component.config
|
|
372
|
-
if value >= conf.get('max',
|
|
373
|
-
value = conf.get('max',
|
|
373
|
+
if value >= conf.get('max', 100):
|
|
374
|
+
value = conf.get('max', 100)
|
|
374
375
|
elif value < conf.get('min', 0):
|
|
375
376
|
value = conf.get('min', 0)
|
|
376
377
|
|
|
377
|
-
if value >= conf.get('max',
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
if value >= conf.get('max', 100):
|
|
379
|
+
if conf.get('inverse') == True:
|
|
380
|
+
pwm_value = 0
|
|
381
|
+
else:
|
|
382
|
+
pwm_value = 1023
|
|
383
|
+
elif value <= conf.get('min', 0):
|
|
384
|
+
if conf.get('inverse') == True:
|
|
385
|
+
pwm_value = 1023
|
|
386
|
+
else:
|
|
387
|
+
pwm_value = 0
|
|
381
388
|
else:
|
|
382
|
-
val_amplitude = conf.get('max',
|
|
389
|
+
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
383
390
|
val_relative = value / val_amplitude
|
|
384
391
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
392
|
+
if conf.get('inverse') == True:
|
|
393
|
+
duty_max = 1023 - conf.get('device_min', 0) / 10 * 1023
|
|
394
|
+
duty_min = 1023 - conf.get('device_max', 10) / 10 * 1023
|
|
395
|
+
pwm_amplitude = duty_max - duty_min
|
|
396
|
+
pwm_value = duty_min + pwm_amplitude * val_relative
|
|
397
|
+
pwm_value = duty_max - pwm_value + duty_min
|
|
398
|
+
else:
|
|
399
|
+
duty_max = conf.get('device_max', 10) / 10 * 1023
|
|
400
|
+
duty_min = conf.get('device_min', 0) / 10 * 1023
|
|
401
|
+
pwm_amplitude = duty_max - duty_min
|
|
402
|
+
pwm_value = duty_min + pwm_amplitude * val_relative
|
|
390
403
|
|
|
391
404
|
return pwm_value
|
|
392
405
|
|
|
393
406
|
def _prepare_for_set(self, pwm_value):
|
|
394
407
|
conf = self.component.config
|
|
395
|
-
|
|
396
|
-
|
|
408
|
+
if conf.get('inverse') == True:
|
|
409
|
+
pwm_value = 1023 - pwm_value
|
|
410
|
+
duty_max = conf.get('device_max', 10) / 10 * 1023
|
|
411
|
+
duty_min = conf.get('device_min', 0) / 10 * 1023
|
|
397
412
|
|
|
398
413
|
if pwm_value > duty_max:
|
|
399
|
-
value = conf.get('max',
|
|
414
|
+
value = conf.get('max', 100)
|
|
400
415
|
elif pwm_value < duty_min:
|
|
401
416
|
value = conf.get('min', 0)
|
|
402
417
|
else:
|
|
403
418
|
pwm_amplitude = duty_max - duty_min
|
|
404
419
|
relative_value = (pwm_value - duty_min) / pwm_amplitude
|
|
405
|
-
val_amplitude = conf.get('max',
|
|
420
|
+
val_amplitude = conf.get('max', 100) - conf.get('min', 0)
|
|
406
421
|
value = conf.get('min', 0) + val_amplitude * relative_value
|
|
407
422
|
|
|
408
423
|
return round(value, 3)
|
|
409
424
|
|
|
410
425
|
|
|
411
|
-
class RGBLight(
|
|
426
|
+
class RGBLight(FleetDeviceMixin, BasicOutputMixin, BaseRGBWLight):
|
|
412
427
|
config_form = ColonelRGBLightConfigForm
|
|
413
428
|
|
|
414
429
|
|
|
415
|
-
class DualMotorValve(
|
|
430
|
+
class DualMotorValve(FleetDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
416
431
|
gateway_class = FleetGatewayHandler
|
|
417
432
|
config_form = DualMotorValveForm
|
|
418
433
|
name = "Dual Motor Valve"
|
|
@@ -444,7 +459,7 @@ class DualMotorValve(FleeDeviceMixin, BasicOutputMixin, BaseDimmer):
|
|
|
444
459
|
return conf.get('min', 0) + (value / 100) * val_amplitude
|
|
445
460
|
|
|
446
461
|
|
|
447
|
-
class Blinds(
|
|
462
|
+
class Blinds(FleetDeviceMixin, BasicOutputMixin, BaseBlinds):
|
|
448
463
|
gateway_class = FleetGatewayHandler
|
|
449
464
|
config_form = BlindsConfigForm
|
|
450
465
|
|
|
@@ -459,7 +474,7 @@ class Blinds(FleeDeviceMixin, BasicOutputMixin, BaseBlinds):
|
|
|
459
474
|
return pins
|
|
460
475
|
|
|
461
476
|
|
|
462
|
-
class Gate(
|
|
477
|
+
class Gate(FleetDeviceMixin, BasicOutputMixin, BaseGate):
|
|
463
478
|
gateway_class = FleetGatewayHandler
|
|
464
479
|
config_form = GateConfigForm
|
|
465
480
|
|
|
@@ -475,7 +490,7 @@ class Gate(FleeDeviceMixin, BasicOutputMixin, BaseGate):
|
|
|
475
490
|
|
|
476
491
|
|
|
477
492
|
|
|
478
|
-
class TTLock(
|
|
493
|
+
class TTLock(FleetDeviceMixin, Lock):
|
|
479
494
|
gateway_class = FleetGatewayHandler
|
|
480
495
|
config_form = TTLockConfigForm
|
|
481
496
|
name = 'TTLock'
|
|
@@ -666,7 +681,7 @@ class TTLock(FleeDeviceMixin, Lock):
|
|
|
666
681
|
|
|
667
682
|
|
|
668
683
|
|
|
669
|
-
class DALIDevice(
|
|
684
|
+
class DALIDevice(FleetDeviceMixin, ControllerBase):
|
|
670
685
|
gateway_class = FleetGatewayHandler
|
|
671
686
|
config_form = DALIDeviceConfigForm
|
|
672
687
|
name = "DALI Device"
|
|
@@ -785,7 +800,7 @@ class DALILamp(FadeMixin, BaseDimmer, DALIDevice):
|
|
|
785
800
|
config_form = DaliLampForm
|
|
786
801
|
|
|
787
802
|
|
|
788
|
-
class DALIGearGroup(FadeMixin,
|
|
803
|
+
class DALIGearGroup(FadeMixin, FleetDeviceMixin, BaseDimmer):
|
|
789
804
|
gateway_class = FleetGatewayHandler
|
|
790
805
|
family = 'dali'
|
|
791
806
|
manual_add = True
|
|
@@ -844,7 +859,7 @@ class DALIButton(BaseButton, DALIDevice):
|
|
|
844
859
|
config_form = DALIButtonConfigForm
|
|
845
860
|
|
|
846
861
|
|
|
847
|
-
class RoomSensor(
|
|
862
|
+
class RoomSensor(FleetDeviceMixin, ControllerBase):
|
|
848
863
|
gateway_class = FleetGatewayHandler
|
|
849
864
|
config_form = RoomSensorDeviceConfigForm
|
|
850
865
|
name = "Room Sensor"
|
|
@@ -854,9 +869,49 @@ class RoomSensor(FleeDeviceMixin, ControllerBase):
|
|
|
854
869
|
|
|
855
870
|
def _validate_val(self, value, occasion=None):
|
|
856
871
|
return value
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
class RoomSiren(FleetDeviceMixin, StateSelect):
|
|
875
|
+
gateway_class = FleetGatewayHandler
|
|
876
|
+
config_form = BaseComponentForm
|
|
877
|
+
default_config = {'states': [
|
|
878
|
+
{'icon': 'bell', 'slug': 'silent', 'name': "Silent"},
|
|
879
|
+
{'icon': 'bell-exclamation', 'slug': 'warning', 'name': "Warning"},
|
|
880
|
+
{'icon': 'bell-on', 'slug': 'alarm', 'name': "Alarm"},
|
|
881
|
+
{'icon': 'circle-check', 'slug': 'success', 'name': "Success"},
|
|
882
|
+
{'icon': 'circle-xmark', 'slug': 'error', 'name': "Error"},
|
|
883
|
+
{'icon': 'siren-on', 'slug': 'panic', 'name': "Panic"},
|
|
884
|
+
]}
|
|
885
|
+
VALUES_MAP = {
|
|
886
|
+
'silent': 0, 'warning': 1, 'alarm': 2,
|
|
887
|
+
'success': 3, 'error': 4, 'panic': 5
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
def turn_on(self):
|
|
891
|
+
self.send('panic')
|
|
892
|
+
|
|
893
|
+
def turn_off(self):
|
|
894
|
+
self.send('silent')
|
|
895
|
+
|
|
896
|
+
def _send_to_device(self, value):
|
|
897
|
+
if self.component.config.get('colonel'):
|
|
898
|
+
GatewayObjectCommand(
|
|
899
|
+
self.component.gateway, self.component, set_val=value
|
|
900
|
+
).publish()
|
|
901
|
+
else:
|
|
902
|
+
dali_device = CustomDaliDevice.objects.filter(
|
|
903
|
+
id=self.component.config['dali_device']
|
|
904
|
+
).first()
|
|
905
|
+
from .custom_dali_operations import Frame
|
|
906
|
+
frame = Frame(40, bytes(bytearray(5)))
|
|
907
|
+
frame[8:11] = 15 # command to custom dali device
|
|
908
|
+
frame[12:15] = 6 # action to perform: set value
|
|
909
|
+
frame[16:20] = 0 # device on which to perform value set
|
|
910
|
+
frame[21:24] = self.VALUES_MAP[value]
|
|
911
|
+
dali_device.transmit(frame)
|
|
857
912
|
|
|
858
913
|
|
|
859
|
-
class AirQualitySensor(
|
|
914
|
+
class AirQualitySensor(FleetDeviceMixin, BaseMultiSensor):
|
|
860
915
|
gateway_class = FleetGatewayHandler
|
|
861
916
|
config_form = BaseComponentForm
|
|
862
917
|
name = "Air Quality Sensor"
|
|
@@ -901,7 +956,7 @@ class AirQualitySensor(FleeDeviceMixin, BaseMultiSensor):
|
|
|
901
956
|
return
|
|
902
957
|
|
|
903
958
|
|
|
904
|
-
class TempHumSensor(
|
|
959
|
+
class TempHumSensor(FleetDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
905
960
|
gateway_class = FleetGatewayHandler
|
|
906
961
|
config_form = BaseComponentForm
|
|
907
962
|
name = "Temperature & Humidity sensor"
|
|
@@ -956,7 +1011,7 @@ class TempHumSensor(FleeDeviceMixin, BasicSensorMixin, BaseMultiSensor):
|
|
|
956
1011
|
return super()._receive_from_device(new_val, *args, **kwargs)
|
|
957
1012
|
|
|
958
1013
|
|
|
959
|
-
class AmbientLightSensor(
|
|
1014
|
+
class AmbientLightSensor(FleetDeviceMixin, BaseNumericSensor):
|
|
960
1015
|
gateway_class = FleetGatewayHandler
|
|
961
1016
|
name = "Ambient lighting sensor"
|
|
962
1017
|
manual_add = False
|
|
@@ -971,13 +1026,13 @@ class AmbientLightSensor(FleeDeviceMixin, BaseNumericSensor):
|
|
|
971
1026
|
}
|
|
972
1027
|
|
|
973
1028
|
|
|
974
|
-
class RoomPresenceSensor(
|
|
1029
|
+
class RoomPresenceSensor(FleetDeviceMixin, BaseBinarySensor):
|
|
975
1030
|
gateway_class = FleetGatewayHandler
|
|
976
1031
|
name = "Human presence sensor"
|
|
977
1032
|
manual_add = False
|
|
978
1033
|
|
|
979
1034
|
|
|
980
|
-
class RoomZonePresenceSensor(
|
|
1035
|
+
class RoomZonePresenceSensor(FleetDeviceMixin, BaseBinarySensor):
|
|
981
1036
|
gateway_class = FleetGatewayHandler
|
|
982
1037
|
add_form = RoomZonePresenceConfigForm
|
|
983
1038
|
config_form = BaseComponentForm
|
|
@@ -2,7 +2,7 @@ from django.utils import timezone
|
|
|
2
2
|
from simo.core.models import Component
|
|
3
3
|
from .models import Interface, CustomDaliDevice
|
|
4
4
|
from .controllers import (
|
|
5
|
-
TempHumSensor, AirQualitySensor, AmbientLightSensor,
|
|
5
|
+
RoomSiren, TempHumSensor, AirQualitySensor, AmbientLightSensor,
|
|
6
6
|
RoomPresenceSensor, RoomZonePresenceSensor
|
|
7
7
|
)
|
|
8
8
|
|
|
@@ -234,6 +234,7 @@ def process_frame(colonel_id, interface_no, data):
|
|
|
234
234
|
comp.controller._receive_from_device(voc)
|
|
235
235
|
|
|
236
236
|
elif frame[8:11] == 1:
|
|
237
|
+
# presence sensors
|
|
237
238
|
comp = Component.objects.filter(
|
|
238
239
|
controller_uid=AmbientLightSensor.uid, config__dali_device=device.id
|
|
239
240
|
).first()
|
|
@@ -272,4 +273,15 @@ def process_frame(colonel_id, interface_no, data):
|
|
|
272
273
|
# was never successfully created
|
|
273
274
|
if zone_sensors[slot].alive:
|
|
274
275
|
zone_sensors[slot].alive = False
|
|
275
|
-
zone_sensors[slot].save()
|
|
276
|
+
zone_sensors[slot].save()
|
|
277
|
+
|
|
278
|
+
elif frame[8:11] == 2:
|
|
279
|
+
# siren and others
|
|
280
|
+
comp = Component.objects.filter(
|
|
281
|
+
controller_uid=RoomSiren.uid, config__dali_device=device.id
|
|
282
|
+
).first()
|
|
283
|
+
if comp:
|
|
284
|
+
VALUES_MAP = {
|
|
285
|
+
int_v: str_v for str_v, int_v in RoomSiren.VALUES_MAP.items()
|
|
286
|
+
}
|
|
287
|
+
comp.controller._receive_from_device(VALUES_MAP[frame[12:16]])
|
simo/fleet/forms.py
CHANGED
|
@@ -689,7 +689,75 @@ class ColonelSwitchConfigForm(ColonelComponentForm):
|
|
|
689
689
|
return obj
|
|
690
690
|
|
|
691
691
|
|
|
692
|
-
class
|
|
692
|
+
class PWMOutputBaseConfig(ColonelComponentForm):
|
|
693
|
+
|
|
694
|
+
def __init__(self, *args, **kwargs):
|
|
695
|
+
super().__init__(*args, **kwargs)
|
|
696
|
+
if 'value_units' in self.fields:
|
|
697
|
+
self.fields['value_units'].initial = self.controller.default_value_units
|
|
698
|
+
self.basic_fields.extend(
|
|
699
|
+
['value_units', 'turn_on_time', 'turn_off_time', 'skew']
|
|
700
|
+
)
|
|
701
|
+
if self.instance.pk and 'slaves' in self.fields:
|
|
702
|
+
self.fields['slaves'].initial = self.instance.slaves.all()
|
|
703
|
+
|
|
704
|
+
def clean_slaves(self):
|
|
705
|
+
if not self.cleaned_data['slaves'] or not self.instance:
|
|
706
|
+
return self.cleaned_data['slaves']
|
|
707
|
+
return validate_slaves(self.cleaned_data['slaves'], self.instance)
|
|
708
|
+
|
|
709
|
+
def clean(self):
|
|
710
|
+
super().clean()
|
|
711
|
+
if 'output_pin' in self.cleaned_data:
|
|
712
|
+
self._clean_pin('output_pin')
|
|
713
|
+
if 'controls' in self.cleaned_data:
|
|
714
|
+
self._clean_controls()
|
|
715
|
+
|
|
716
|
+
if self.cleaned_data.get('output_pin') and self.cleaned_data.get('controls'):
|
|
717
|
+
for ctrl in self.cleaned_data['controls']:
|
|
718
|
+
if not ctrl['input'].startswith('pin'):
|
|
719
|
+
continue
|
|
720
|
+
if int(ctrl['input'][4:]) == self.cleaned_data['output_pin'].id:
|
|
721
|
+
self.add_error(
|
|
722
|
+
"output_pin",
|
|
723
|
+
"Can't be used as control pin at the same time!"
|
|
724
|
+
)
|
|
725
|
+
return self.cleaned_data
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
def save(self, commit=True):
|
|
729
|
+
if 'output_pin' in self.cleaned_data:
|
|
730
|
+
self.instance.config['output_pin_no'] = self.cleaned_data['output_pin'].no
|
|
731
|
+
|
|
732
|
+
update_colonel = False
|
|
733
|
+
if not self.instance.pk:
|
|
734
|
+
update_colonel = True
|
|
735
|
+
elif 'output_pin' in self.changed_data:
|
|
736
|
+
update_colonel = True
|
|
737
|
+
elif 'slaves' in self.changed_data:
|
|
738
|
+
update_colonel = True
|
|
739
|
+
if not update_colonel:
|
|
740
|
+
old = Component.objects.get(id=self.instance.id)
|
|
741
|
+
if old.config.get('controls') != self.cleaned_data.get('controls'):
|
|
742
|
+
update_colonel = True
|
|
743
|
+
|
|
744
|
+
obj = super().save(commit=commit)
|
|
745
|
+
if commit and 'slaves' in self.cleaned_data:
|
|
746
|
+
obj.slaves.set(self.cleaned_data['slaves'])
|
|
747
|
+
if not update_colonel:
|
|
748
|
+
GatewayObjectCommand(
|
|
749
|
+
obj.gateway, self.cleaned_data['colonel'], id=obj.id,
|
|
750
|
+
command='call', method='update_config', args=[
|
|
751
|
+
obj.controller._get_colonel_config()
|
|
752
|
+
]
|
|
753
|
+
).publish()
|
|
754
|
+
if commit and self.cleaned_data.get('controls'):
|
|
755
|
+
GatewayObjectCommand(
|
|
756
|
+
self.instance.gateway, obj, command='watch_buttons'
|
|
757
|
+
).publish()
|
|
758
|
+
return obj
|
|
759
|
+
|
|
760
|
+
class ColonelPWMOutputConfigForm(PWMOutputBaseConfig):
|
|
693
761
|
output_pin = Select2ModelChoiceField(
|
|
694
762
|
label="Port",
|
|
695
763
|
queryset=ColonelPin.objects.filter(output=True),
|
|
@@ -758,74 +826,8 @@ class ColonelPWMOutputConfigForm(ColonelComponentForm):
|
|
|
758
826
|
)
|
|
759
827
|
)
|
|
760
828
|
|
|
761
|
-
def __init__(self, *args, **kwargs):
|
|
762
|
-
super().__init__(*args, **kwargs)
|
|
763
|
-
if 'value_units' in self.fields:
|
|
764
|
-
self.fields['value_units'].initial = self.controller.default_value_units
|
|
765
|
-
self.basic_fields.extend(
|
|
766
|
-
['value_units', 'turn_on_time', 'turn_off_time', 'skew']
|
|
767
|
-
)
|
|
768
|
-
if self.instance.pk and 'slaves' in self.fields:
|
|
769
|
-
self.fields['slaves'].initial = self.instance.slaves.all()
|
|
770
|
-
|
|
771
|
-
def clean_slaves(self):
|
|
772
|
-
if not self.cleaned_data['slaves'] or not self.instance:
|
|
773
|
-
return self.cleaned_data['slaves']
|
|
774
|
-
return validate_slaves(self.cleaned_data['slaves'], self.instance)
|
|
775
|
-
|
|
776
|
-
def clean(self):
|
|
777
|
-
super().clean()
|
|
778
|
-
if 'output_pin' in self.cleaned_data:
|
|
779
|
-
self._clean_pin('output_pin')
|
|
780
|
-
if 'controls' in self.cleaned_data:
|
|
781
|
-
self._clean_controls()
|
|
782
|
-
|
|
783
|
-
if self.cleaned_data.get('output_pin') and self.cleaned_data.get('controls'):
|
|
784
|
-
for ctrl in self.cleaned_data['controls']:
|
|
785
|
-
if not ctrl['input'].startswith('pin'):
|
|
786
|
-
continue
|
|
787
|
-
if int(ctrl['input'][4:]) == self.cleaned_data['output_pin'].id:
|
|
788
|
-
self.add_error(
|
|
789
|
-
"output_pin",
|
|
790
|
-
"Can't be used as control pin at the same time!"
|
|
791
|
-
)
|
|
792
|
-
return self.cleaned_data
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
def save(self, commit=True):
|
|
796
|
-
if 'output_pin' in self.cleaned_data:
|
|
797
|
-
self.instance.config['output_pin_no'] = self.cleaned_data['output_pin'].no
|
|
798
|
-
|
|
799
|
-
update_colonel = False
|
|
800
|
-
if not self.instance.pk:
|
|
801
|
-
update_colonel = True
|
|
802
|
-
elif 'output_pin' in self.changed_data:
|
|
803
|
-
update_colonel = True
|
|
804
|
-
elif 'slaves' in self.changed_data:
|
|
805
|
-
update_colonel = True
|
|
806
|
-
if not update_colonel:
|
|
807
|
-
old = Component.objects.get(id=self.instance.id)
|
|
808
|
-
if old.config.get('controls') != self.cleaned_data.get('controls'):
|
|
809
|
-
update_colonel = True
|
|
810
829
|
|
|
811
|
-
|
|
812
|
-
if commit and 'slaves' in self.cleaned_data:
|
|
813
|
-
obj.slaves.set(self.cleaned_data['slaves'])
|
|
814
|
-
if not update_colonel:
|
|
815
|
-
GatewayObjectCommand(
|
|
816
|
-
obj.gateway, self.cleaned_data['colonel'], id=obj.id,
|
|
817
|
-
command='call', method='update_config', args=[
|
|
818
|
-
obj.controller._get_colonel_config()
|
|
819
|
-
]
|
|
820
|
-
).publish()
|
|
821
|
-
if commit and self.cleaned_data.get('controls'):
|
|
822
|
-
GatewayObjectCommand(
|
|
823
|
-
self.instance.gateway, obj, command='watch_buttons'
|
|
824
|
-
).publish()
|
|
825
|
-
return obj
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
class DCDriverConfigForm(ColonelComponentForm):
|
|
830
|
+
class DC10VConfigForm(PWMOutputBaseConfig):
|
|
829
831
|
output_pin = Select2ModelChoiceField(
|
|
830
832
|
label="Port",
|
|
831
833
|
queryset=ColonelPin.objects.filter(output=True),
|
|
@@ -841,53 +843,60 @@ class DCDriverConfigForm(ColonelComponentForm):
|
|
|
841
843
|
help_text="Minimum component value displayed to the user."
|
|
842
844
|
)
|
|
843
845
|
max = forms.FloatField(
|
|
844
|
-
required=True, initial=
|
|
846
|
+
required=True, initial=100,
|
|
845
847
|
help_text="Maximum component value displayed to the user."
|
|
846
848
|
)
|
|
847
|
-
value_units = forms.CharField(required=False)
|
|
849
|
+
value_units = forms.CharField(required=False, initial='%')
|
|
848
850
|
|
|
849
851
|
device_min = forms.FloatField(
|
|
850
852
|
label="Device minimum Voltage.",
|
|
851
853
|
help_text="This will be the lowest possible voltage value of a device.\n"
|
|
852
854
|
"Don't forget to adjust your component min value accordingly "
|
|
853
855
|
"if you change this.",
|
|
854
|
-
initial=0, min_value=0, max_value=
|
|
856
|
+
initial=0, min_value=0, max_value=10,
|
|
855
857
|
)
|
|
856
|
-
device_max = forms.
|
|
858
|
+
device_max = forms.FloatField(
|
|
857
859
|
label="Device maximum Voltage.",
|
|
858
|
-
help_text="Can be set lower than it's natural maximum of
|
|
860
|
+
help_text="Can be set lower than it's natural maximum of 10V. \n"
|
|
859
861
|
"Don't forget to adjust your component max value accordingly "
|
|
860
862
|
"if you change this.",
|
|
861
|
-
initial=
|
|
863
|
+
initial=10, min_value=0, max_value=10,
|
|
862
864
|
)
|
|
865
|
+
inverse = forms.BooleanField(required=False, initial=False)
|
|
863
866
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
867
|
+
turn_on_time = forms.IntegerField(
|
|
868
|
+
min_value=0, max_value=60000, initial=0,
|
|
869
|
+
help_text="Turn on speed in ms. 1500 is a great quick default for controlling lights. "
|
|
870
|
+
"10000 - great slow default."
|
|
871
|
+
)
|
|
872
|
+
turn_off_time = forms.IntegerField(
|
|
873
|
+
min_value=0, max_value=60000, initial=0,
|
|
874
|
+
help_text="Turn off speed in ms. 3000 is a great quick default when controlling lights. "
|
|
875
|
+
"20000 - great slow default"
|
|
876
|
+
)
|
|
877
|
+
skew = forms.ChoiceField(
|
|
878
|
+
initial='linear', choices=EASING_CHOICES,
|
|
879
|
+
help_text="easeOutSine - offers most naturally looking effect for lights."
|
|
880
|
+
)
|
|
881
|
+
on_value = forms.FloatField(
|
|
882
|
+
required=False,
|
|
883
|
+
help_text="Static ON value used to turn on the device with physical controls. <br>"
|
|
884
|
+
"Leaving this field empty turns the device on to the last used value."
|
|
885
|
+
)
|
|
882
886
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
887
|
+
slaves = Select2ModelMultipleChoiceField(
|
|
888
|
+
queryset=Component.objects.filter(
|
|
889
|
+
base_type__in=('dimmer',),
|
|
890
|
+
),
|
|
891
|
+
url='autocomplete-component',
|
|
892
|
+
forward=(forward.Const(['dimmer', ], 'base_type'),),
|
|
893
|
+
required=False
|
|
894
|
+
)
|
|
895
|
+
controls = FormsetField(
|
|
896
|
+
formset_factory(
|
|
897
|
+
ControlForm, can_delete=True, can_order=True, extra=0, max_num=10
|
|
898
|
+
)
|
|
899
|
+
)
|
|
891
900
|
|
|
892
901
|
|
|
893
902
|
class ColonelRGBLightConfigForm(ColonelComponentForm):
|
|
@@ -1814,6 +1823,7 @@ class CustomDaliDeviceForm(BaseComponentForm):
|
|
|
1814
1823
|
|
|
1815
1824
|
class RoomSensorDeviceConfigForm(CustomDaliDeviceForm):
|
|
1816
1825
|
|
|
1826
|
+
|
|
1817
1827
|
def save(self, commit=True):
|
|
1818
1828
|
from simo.core.models import Icon
|
|
1819
1829
|
colonel = None
|
|
@@ -1827,13 +1837,14 @@ class RoomSensorDeviceConfigForm(CustomDaliDeviceForm):
|
|
|
1827
1837
|
colonel = device
|
|
1828
1838
|
|
|
1829
1839
|
from .controllers import (
|
|
1830
|
-
AirQualitySensor, TempHumSensor, AmbientLightSensor,
|
|
1840
|
+
RoomSiren, AirQualitySensor, TempHumSensor, AmbientLightSensor,
|
|
1831
1841
|
RoomPresenceSensor
|
|
1832
1842
|
)
|
|
1833
1843
|
|
|
1834
1844
|
org_name = self.cleaned_data['name']
|
|
1835
1845
|
org_icon = self.cleaned_data['icon']
|
|
1836
1846
|
for CtrlClass, icon, suffix in (
|
|
1847
|
+
(RoomSiren, 'siren', 'siren'),
|
|
1837
1848
|
(AirQualitySensor, 'leaf', 'air quality'),
|
|
1838
1849
|
(TempHumSensor, 'temperature-half', 'temperature'),
|
|
1839
1850
|
(AmbientLightSensor, 'brightness-low', 'brightness'),
|