diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 49c9d6d..2e37b4d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,6 +19,7 @@ repos: additional_dependencies: - mdformat-toc - mdformat-beautysh + - setuptools # workaround for beautysh # -mdformat-shfmt # -mdformat-tables - mdformat-config @@ -68,6 +69,9 @@ repos: rev: v6.2.1 hooks: - id: beautysh + additional_dependencies: + - setuptools # workaround for beautysh + - repo: https://github.com/shellcheck-py/shellcheck-py rev: v0.10.0.1 hooks: diff --git a/README.md b/README.md index 9808f4d..710f0a4 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ ZHA Toolkit can also: - [`zha_devices`: Device Information to Event or CSV or Script variable](#zha_devices-device-information-to-event-or-csv-or-script-variable) - [`register_services`: Reregister ZHA-Toolkit services](#register_services-reregister-zha-toolkit-services) - [`ha_set_state` - Update HA state](#ha_set_state---update-ha-state) + - [`misc_energy_scan`: Perform an energy scan](#misc_energy_scan-perform-an-energy-scan) - [User method](#user-method) - [Manufacturers](#manufacturers) - [Tuya](#tuya) @@ -1921,6 +1922,49 @@ service code is entered which is incompatible with this functionality. This is not strictly a `zha` specific tool, but useful in some scripting situations. +### `misc_energy_scan`: Perform an energy scan + +Scan Zigbee channels for congestion level. The value is a percentage from +zero to 100. A lower value is less congested. + +```yaml +service: zha_toolkit.misc_energy_scan +data: + # Optional: CSV file to write attribute to - located in /config/csv/... + csvout: energy_scan.csv +``` + +The values can vary quite a bit between scans. You can create helpers to +store results which will allow you to see trends via the History tab. This +automation runs each hour: + +``` + - id: zigbee_energy_scan + alias: Zigbee Energy Scan + mode: single + triggers: + - trigger: time_pattern + # Matches every hour at 17 minutes past the hour + minutes: 17 + actions: + - action: zha_toolkit.execute + data: + command: misc_energy_scan + response_variable: scan + - repeat: + for_each: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] + sequence: + - action: input_number.set_value + target: + entity_id: "input_number.zigbee_energy_channel_{{ repeat.item }}" + data: + value: "{{ scan['energy_scan'][repeat.item] | round }}" +``` + +Creating 16 input_number helpers can be tedious. ZHA recommends only +channels 15, 20, and 25 be used. Alternatively you can create just three +helpers and reduce the for_each list to only those three channels. + ## User method You can add your own Python commands in `local/user.py`. Your file is diff --git a/custom_components/zha_toolkit/misc.py b/custom_components/zha_toolkit/misc.py index 98617e1..da06c54 100644 --- a/custom_components/zha_toolkit/misc.py +++ b/custom_components/zha_toolkit/misc.py @@ -318,3 +318,39 @@ async def misc_settime( except DeliveryError as e: event_data["success"] = False event_data["msg"] = f"{e!r}" + + +async def misc_energy_scan( + app, listener, ieee, cmd, data, service, params, event_data +): + """Run energy scan for each channel.""" + # See https://github.com/zigpy/zigpy-cli/blob/dev/README.md#performing-an-energy-scan # noqa: E501 + # Lower value means less congestion. + + LOGGER.debug("Energy scan.") + scan = await app.energy_scan( + channels=t.Channels.ALL_CHANNELS, duration_exp=4, count=1 + ) + event_data["energy_scan"] = { + channel: 100 * energy / 255 for channel, energy in scan.items() + } + + if params[p.CSV_FILE] is not None: + # write CSV header + u.append_to_csvfile( + ["channel", "energy"], + "csv", + params[p.CSV_FILE], + "Energy Scan", + listener=listener, + overwrite=True, + ) + # write CSV data + for channel, energy in scan.items(): + u.append_to_csvfile( + [channel, 100 * energy / 255], + "csv", + params[p.CSV_FILE], + str(channel), + listener=listener, + )