Skip to content

Commit c31ad40

Browse files
authored
Merge pull request #283 from stu247/energy_scan
Energy scan
2 parents 2d8be5d + 9bee204 commit c31ad40

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

.pre-commit-config.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ repos:
1919
additional_dependencies:
2020
- mdformat-toc
2121
- mdformat-beautysh
22+
- setuptools # workaround for beautysh
2223
# -mdformat-shfmt
2324
# -mdformat-tables
2425
- mdformat-config
@@ -68,6 +69,9 @@ repos:
6869
rev: v6.2.1
6970
hooks:
7071
- id: beautysh
72+
additional_dependencies:
73+
- setuptools # workaround for beautysh
74+
7175
- repo: https://github.com/shellcheck-py/shellcheck-py
7276
rev: v0.10.0.1
7377
hooks:

README.md

+44
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ ZHA Toolkit can also:
122122
- [`zha_devices`: Device Information to Event or CSV or Script variable](#zha_devices-device-information-to-event-or-csv-or-script-variable)
123123
- [`register_services`: Reregister ZHA-Toolkit services](#register_services-reregister-zha-toolkit-services)
124124
- [`ha_set_state` - Update HA state](#ha_set_state---update-ha-state)
125+
- [`misc_energy_scan`: Perform an energy scan](#misc_energy_scan-perform-an-energy-scan)
125126
- [User method](#user-method)
126127
- [Manufacturers](#manufacturers)
127128
- [Tuya](#tuya)
@@ -1921,6 +1922,49 @@ service code is entered which is incompatible with this functionality.
19211922
This is not strictly a `zha` specific tool, but useful in some scripting
19221923
situations.
19231924

1925+
### `misc_energy_scan`: Perform an energy scan
1926+
1927+
Scan Zigbee channels for congestion level. The value is a percentage from
1928+
zero to 100. A lower value is less congested.
1929+
1930+
```yaml
1931+
service: zha_toolkit.misc_energy_scan
1932+
data:
1933+
# Optional: CSV file to write attribute to - located in /config/csv/...
1934+
csvout: energy_scan.csv
1935+
```
1936+
1937+
The values can vary quite a bit between scans. You can create helpers to
1938+
store results which will allow you to see trends via the History tab. This
1939+
automation runs each hour:
1940+
1941+
```
1942+
- id: zigbee_energy_scan
1943+
alias: Zigbee Energy Scan
1944+
mode: single
1945+
triggers:
1946+
- trigger: time_pattern
1947+
# Matches every hour at 17 minutes past the hour
1948+
minutes: 17
1949+
actions:
1950+
- action: zha_toolkit.execute
1951+
data:
1952+
command: misc_energy_scan
1953+
response_variable: scan
1954+
- repeat:
1955+
for_each: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
1956+
sequence:
1957+
- action: input_number.set_value
1958+
target:
1959+
entity_id: "input_number.zigbee_energy_channel_{{ repeat.item }}"
1960+
data:
1961+
value: "{{ scan['energy_scan'][repeat.item] | round }}"
1962+
```
1963+
1964+
Creating 16 input_number helpers can be tedious. ZHA recommends only
1965+
channels 15, 20, and 25 be used. Alternatively you can create just three
1966+
helpers and reduce the for_each list to only those three channels.
1967+
19241968
## User method
19251969

19261970
You can add your own Python commands in `local/user.py`. Your file is

custom_components/zha_toolkit/misc.py

+36
Original file line numberDiff line numberDiff line change
@@ -318,3 +318,39 @@ async def misc_settime(
318318
except DeliveryError as e:
319319
event_data["success"] = False
320320
event_data["msg"] = f"{e!r}"
321+
322+
323+
async def misc_energy_scan(
324+
app, listener, ieee, cmd, data, service, params, event_data
325+
):
326+
"""Run energy scan for each channel."""
327+
# See https://github.com/zigpy/zigpy-cli/blob/dev/README.md#performing-an-energy-scan # noqa: E501
328+
# Lower value means less congestion.
329+
330+
LOGGER.debug("Energy scan.")
331+
scan = await app.energy_scan(
332+
channels=t.Channels.ALL_CHANNELS, duration_exp=4, count=1
333+
)
334+
event_data["energy_scan"] = {
335+
channel: 100 * energy / 255 for channel, energy in scan.items()
336+
}
337+
338+
if params[p.CSV_FILE] is not None:
339+
# write CSV header
340+
u.append_to_csvfile(
341+
["channel", "energy"],
342+
"csv",
343+
params[p.CSV_FILE],
344+
"Energy Scan",
345+
listener=listener,
346+
overwrite=True,
347+
)
348+
# write CSV data
349+
for channel, energy in scan.items():
350+
u.append_to_csvfile(
351+
[channel, 100 * energy / 255],
352+
"csv",
353+
params[p.CSV_FILE],
354+
str(channel),
355+
listener=listener,
356+
)

0 commit comments

Comments
 (0)