From 0244699ec3929d593779edca68da1047ef4695f6 Mon Sep 17 00:00:00 2001 From: Edward Brown Date: Fri, 1 Sep 2023 16:20:37 +0100 Subject: [PATCH] Refine README --- README.md | 76 ++++++++++++++++++++++---------------- assets/greeter_select.png | Bin 0 -> 5237 bytes assets/memory_sensor.png | Bin 0 -> 40990 bytes assets/weblog_select.png | Bin 0 -> 5237 bytes haco/control.py | 2 +- 5 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 assets/greeter_select.png create mode 100644 assets/memory_sensor.png create mode 100644 assets/weblog_select.png diff --git a/README.md b/README.md index 1a330e5..c3f0b1d 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,8 @@ Installation involves installing two parts: the Tasmota daemon and the Home Assi ### Tasmota I'd advise first using a guinea pig Tasmota device to get `haco` up and running. The device needs to have MQTT -connected and be available to Home Assistant (i.e. showing up in the Devices section). +connected and be available to Home Assistant (i.e. showing up +in [the Devices section](https://my.home-assistant.io/redirect/devices/)). Once your test device is ready, with a recent (12.5+) version of Tasmota, simply paste the following into your Tasmota Berry Script Console: @@ -92,9 +93,6 @@ Berry Script Console: You should see output like `{'restart': {'Restart': 'Restarting'}, 'download': 200}` and the device will restart. -With older Tasmota versions, download the [`.tapp` file](https://link.frontmatter.ai/haco/tapp) on a desktop computer, -upload it to your device as `haco.tapp` and restart manually. - Once the device restarts, you should see the following among your Tasmota startup logs (in the regular console, not the Berry one): @@ -102,13 +100,19 @@ Berry one): HACO: The haco daemon has started. Hostname: tasmota-test, MAC: 04:74:77:9B:CB:CC. Listening for configuration... ``` +#### Older Tasmota Versions + +With older Tasmota versions, download the [`haco.tapp` file](https://link.frontmatter.ai/haco/tapp) on a desktop +computer, +upload it to your device and restart manually. + ### Home Assistant You can now install the Home Assistant Add-On: [![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://link.frontmatter.ai/haco/add-on) -Once the Add-On is installed, click into its Configuration tab, you'll see a setting called `assignments`: +Once the Add-On is installed, click into its Configuration tab and you'll see a setting called `assignments`: ```yaml - config: null @@ -132,8 +136,11 @@ Saving the Configuration will restart the Add-On. After the restart, you should Device "Tasmota Test Device" successfully configured. Hostname: tasmota-test MAC: 04:74:77:9B:CB:CC. ``` -In Home Assistant, find the device in the Devices section. You should now see a test Select (pulldown) control called " -Greeter". +In Home Assistant, find the device in [the Devices section](https://my.home-assistant.io/redirect/devices/). You should +now see a test Select (pulldown) control called "Greeter". + +WebLog Select + Selecting the greetings from the pulldown, you should see them appear in your Tasmota Berry console, e.g. ```console @@ -177,7 +184,7 @@ more `Control` objects. Each control definition involves two things: #### Location User-Defined modules should be added to the `/config/haco` directory in Home Assistant, with a `.py` extension, -e.g. `my_config.py`. +e.g. `/config/haco/my_config.py`. #### Defining controls @@ -205,35 +212,38 @@ Let's break this control definition down into the control object, the callback d ###### The control object First we initialise a `Sensor` control object, assign it to a variable called `memory`, give it a relevant icon, unit of -measure and device class. +measure and type. ###### The callback decorator -Next, we add a callback object to that control. Here we call the function `tasmota` to tell `haco` that this callback is -for handling values _from_ Tasmota. As for _what_ -values to return from Tasmota, this is specified by the `trigger` argument to the decorator `memory.callback`. The -trigger itself, `Tele#Heap`, fires -whenever telemetry data is returned from Tasmota and, specifically, returns the `Heap` field, which contains the free -memory in -kilobytes. +The callback decorator `@memory.callback(trigger='Tele#Heap')` specifies a Tasmota trigger, the values from which will +be sent to the callback function. +This specific trigger, `Tele#Heap`, fires whenever telemetry data is returned from Tasmota and, specifically, returns +the `Heap` field, which contains the free +memory in kilobytes. :warning: Tasmota callbacks _must_ have such a `trigger` specified in this decorator. +Memory Sensor + + ###### The callback -Note that the callback function is named `tasmota`. This is important as the name tells `haco` that this callback +Note that the callback function is named `tasmota`. This name is important as it tells `haco` that this callback handles values _from_ Tasmota. + The response from the trigger we specified in our callback decorator above gets fed into our callback as the `value` argument. The (optional) type annotation for the `value` argument (the `int`) tells `haco` what data type to expect from Tasmota, and type conversion gets done automatically. + The return value from the function is what will be returned to Home Assistant as the value for the sensor. :information_source: Note that our callback function does not actually _do_ anything with our `value` other than return -it. But if we wanted to (for example) -convert the value from kilobytes to bytes, this is where we'd do it, with `return value*1000`. +it. But if we wanted to (for example) convert the value from kilobytes to bytes, this is where we'd do it, +with `return value*1000`. -:information_source: You can find the list of available UOMs [here](blob/release/haco/data/uom.py) and -types [here](blob/main/haco/data/type_sensor.py). +:information_source: You can find the list of available units of measure [here](../../blob/release/haco/data/uom.py) and +types [here](../../blob/main/haco/data/type_sensor.py). #### Home Assistant-Only Controls @@ -266,19 +276,20 @@ two arguments, `Tasmota[,]`. The first argument is the type returned by the callback function, as per usual, and which again lets `haco` convert the return value accordingly. -But the second argument is an expression that defines how to _apply_ the change on the Tasmota side. In this case, this +The second argument is an expression that defines _what to do_ on the Tasmota side when the button is pressed. In this +case, this is just a Berry expression to restart Tasmota. :warning: Note that Home Assistant callbacks _must_ have such a `Tasmota` type annotation for their return type. :information_source: In the example above, the `value` argument received and returned by our callback is not actually -used on the Berry -side. Home Assistant just sends a constant string (`PRESS`) when the button is pressed, so the actual content of +used by the Berry expression side. Home Assistant just sends a constant string (`PRESS`) when the button is pressed, so +the actual content of the `value` argument is not important. #### Two-Way Controls -Two-Way controls need to handle values from _both_ Home Assistant and from Tasmota, and hence need both the callbacks +Two-way controls need to handle values from _both_ Home Assistant and from Tasmota, and hence need both the callbacks types - `ha` and `tasmota` we've seen above. Here is an example two-way `Select` (pulldown menu) object. It allows setting the Tasmota `WebLog` console debugging @@ -317,27 +328,28 @@ the `WebLog` command is used on the Tasmota side. When you first assign a new configuration to a device, keep an eye on the Add-On logs for any errors. You'll see a typical Python stack trace if anything goes wrong. -:information_source: Each time you edit your configuration module (`.py` file), you'll need to restart the Add-On. Hot +:warning: Each time you edit your configuration module (`.py` file), you'll need to restart the Add-On. Hot is reloading not yet supported. #### Additional Capabilities -More complex device controls (e.g. `Climate`, `Fan`) have additional capabilities beyond a single value sent to/from -Home Assistant. Adding callbacks for these extended capabilities is done similarly to the above, only the callbacks need +More complex device controls (e.g. `Climate`, `Fan`) have additional capabilities beyond a single value requiting +Tasmota/Home Assistant +callbacks. Adding callbacks for these extended capabilities is done similarly to the above, only the callbacks need to include the name of the capability. So if you want to add callbacks around setting the `target_humidity` of a `Climate` control, you'd need to call your callbacks `target_humidity_tasmota` and `target_humidity_ha`, etc. A full schema of these names will appear in subsequent documentation. But you can find example implementations for most -controls in the [built-in `development` config](blob/release/haco/configs/development.py). +controls in the [built-in `development` config](../../blob/release/haco/configs/development.py). Anway, if you get the names wrong, you'll see an error like this in your Add-On logs: ``` -ValueError: Callback function "set_mode_ha" name is not valid for control "Climate". Must be one of: ['action_tasmota', 'current_humidity_tasmota', 'current_temperature_tasmota', 'mode_ha', 'mode_tasmota', 'preset_mode_ha', 'preset_mode_tasmota', 'swing_mode_ha', 'swing_mode_tasmota', 'target_humidity_ha', 'target_humidity_tasmota', 'target_temperature_ha', 'target_temperature_tasmota', 'temperature_high_ha', 'temperature_high_tasmota', 'temperature_low_ha', 'temperature_low_tasmota'] +ValueError: Callback function name "set_mode_ha" is not valid for control "Climate". Must be one of: ['action_tasmota', 'current_humidity_tasmota', 'current_temperature_tasmota', 'mode_ha', 'mode_tasmota', 'preset_mode_ha', 'preset_mode_tasmota', 'swing_mode_ha', 'swing_mode_tasmota', 'target_humidity_ha', 'target_humidity_tasmota', 'target_temperature_ha', 'target_temperature_tasmota', 'temperature_high_ha', 'temperature_high_tasmota', 'temperature_low_ha', 'temperature_low_tasmota'] ``` #### Additional Resources Beyond these examples, when creating your own configuration, you'll probably find -the [built-in configurations](tree/release/haco/configs) ( -especially the [`development` config](blob/release/haco/configs/development.py)) useful. +the [built-in configurations](../../tree/release/haco/configs) (especially +the [`development` config](../../blob/release/haco/configs/development.py)) useful. diff --git a/assets/greeter_select.png b/assets/greeter_select.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3546fe785251d64d50f78f1dfbbf69cc98e185 GIT binary patch literal 5237 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≈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 i*1w9jRgn0wxqe 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 literal 0 HcmV?d00001 diff --git a/haco/control.py b/haco/control.py index c971a82..20bb0b8 100644 --- a/haco/control.py +++ b/haco/control.py @@ -54,7 +54,7 @@ class Control: callback_names = self.schema.get_callback_function_names() if function_name not in callback_names: - msg = f'Callback function "{function_name}" name is not valid for control "{self.__class__.__name__}". Must be one of: {sorted(callback_names)}' + msg = f'Callback function name "{function_name}" is not valid for control "{self.__class__.__name__}". Must be one of: {sorted(callback_names)}' raise ValueError(msg) capability_id, platform_id = function_name.rsplit('_', 1)