joshuar-go-hass-agent/README.md

859 lines
35 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
Copyright (c) 2024 Joshua Rich <joshua.rich@gmail.com>
This software is released under the MIT License.
https://opensource.org/licenses/MIT
-->
<div align="center">
<img src="internal/agent/ui/assets/go-hass-agent.png" alt="logo" width="200" height="auto" />
<h1>Go Hass Agent</h1>
<p>
A <a href="https://www.home-assistant.io/">Home Assistant</a>, <a href="https://developers.home-assistant.io/docs/api/native-app-integration">native app
integration</a> for desktop/laptop devices.
</p>
<!-- Badges -->
<p>
<a href="https://github.com/joshuar/go-hass-agent/graphs/contributors">
<img src="https://img.shields.io/github/contributors/joshuar/go-hass-agent" alt="contributors" />
</a>
<a href="">
<img src="https://img.shields.io/github/last-commit/joshuar/go-hass-agent" alt="last update" />
</a>
<a href="https://github.com/joshuar/go-hass-agent/network/members">
<img src="https://img.shields.io/github/forks/joshuar/go-hass-agent" alt="forks" />
</a>
<a href="https://github.com/joshuar/go-hass-agent/stargazers">
<img src="https://img.shields.io/github/stars/joshuar/go-hass-agent" alt="stars" />
</a>
<a href="https://github.com/joshuar/go-hass-agent/issues/">
<img src="https://img.shields.io/github/issues/joshuar/go-hass-agent" alt="open issues" />
</a>
<a href="https://github.com/joshuar/go-hass-agent/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/joshuar/go-hass-agent.svg" alt="license" />
</a>
</p>
<h4>
<a href="https://github.com/joshuar/go-hass-agent">Documentation</a>
<span> · </span>
<a href="https://github.com/joshuar/go-hass-agent/issues/new?assignees=joshuar&labels=&template=bug_report.md&title=%5BBUG%5D">Report Bug</a>
<span> · </span>
<a href="https://github.com/joshuar/go-hass-agent/issues/new?assignees=joshuar&labels=&template=feature_request.md&title=">Request Feature</a>
</h4>
</div>
<br />
<!-- Table of Contents -->
## :notebook_with_decorative_cover: Table of Contents
- [:notebook\_with\_decorative\_cover: Table of Contents](#notebook_with_decorative_cover-table-of-contents)
- [:star2: About the Project](#star2-about-the-project)
- [:dart: Features](#dart-features)
- [📈 Sensors (by Operating System)](#-sensors-by-operating-system)
- [:penguin: Linux](#penguin-linux)
- [:robot: Script Sensors (All Platforms)](#robot-script-sensors-all-platforms)
- [:bus: Control via MQTT (All Platforms)](#bus-control-via-mqtt-all-platforms)
- [🤔 Use-cases](#-use-cases)
- [🗒️ Versioning](#-versioning)
- [:toolbox: Getting Started](#toolbox-getting-started)
- [🤝 Compatibility](#-compatibility)
- [:gear: Installation](#gear-installation)
- [📦 Packages](#-packages)
- [🚢 Container](#-container)
- [:eyes: Usage](#eyes-usage)
- [🔛 First-run](#-first-run)
- [Running “Headless”](#running-headless)
- [Running in a container](#running-in-a-container)
- [Regular Usage](#regular-usage)
- [Configuration Location](#configuration-location)
- [Script Sensors](#script-sensors)
- [Requirements](#requirements)
- [Supported Scripting Languages](#supported-scripting-languages)
- [Output Format](#output-format)
- [Examples](#examples)
- [JSON](#json)
- [YAML](#yaml)
- [TOML](#toml)
- [Schedule](#schedule)
- [Security Implications](#security-implications)
- [Controls (via MQTT)](#controls-via-mqtt)
- [Requirements](#requirements-1)
- [Configuration](#configuration)
- [Available Controls](#available-controls)
- [Custom D-BUS Controls](#custom-d-bus-controls)
- [Other Custom Commands](#other-custom-commands)
- [Security Implications](#security-implications-1)
- [:compass: Roadmap](#compass-roadmap)
- [:wave: Contributing](#wave-contributing)
- [:scroll: Code of Conduct](#scroll-code-of-conduct)
- [:grey\_question: FAQ](#grey_question-faq)
- [:gem: Acknowledgements](#gem-acknowledgements)
- [:warning: License](#warning-license)
<!-- About the Project -->
## :star2: About the Project
<!-- Features -->
### :dart: Features
#### 📈 Sensors (by Operating System)
> [!NOTE]
> The following list shows all **potential** sensors the agent can
> report. In some cases, the **actual** sensors reported may be less due to
> lack of support in the system configuration or missing hardware.
##### :penguin: Linux
- *Go Hass Agent Version*. Updated on agent start.
- App Details:
- *Active App* (currently active (focused) application) and *Running Apps*
(count of all running applications). Updated when active app or number of apps
changes.
- Via D-Bus (requires [XDG Desktop Portal
Support](https://flatpak.github.io/xdg-desktop-portal/docs/) support).
- Desktop Settings:
- *Accent Colour* (the hex code representing the accent colour of the desktop
environment in use) and *Theme Type* (whether a dark or light desktop theme is
detected). Updated when theme or colour changes.
- Via D-Bus (requires [XDG Desktop Portal
Support](https://flatpak.github.io/xdg-desktop-portal/docs/) support).
- Connected Battery Details:
- *Battery Type* (the type of battery, e.g., UPS, line power). Updated on battery add/remove.
- *Battery Temp* (battery temperature). Updated when the temperature changes.
- *Battery Power* (the battery current power draw, in W). Attributes: Voltage
(V), Energy consumption (kWh). Updated when power draw changes.
- *Battery Level/Percentage* (either a textual representation of the level or
a percentage, depending on battery support). Updated when level changes.
- *Battery State* (the current battery state, e.g., charging/discharging).
Updated When state changes.
- All battery sensors require D-Bus and
[Upower](https://upower.freedesktop.org/) support.
- Memory Stats:
- *Memory Total* (total memory on the system, in B).
- *Memory Available* (current memory available/free, in B).
- *Memory Used* (current memory usage, both in B and %).
- If swap is enabled, there will be similar sensors for swap.
- Sourced via ProcFS. Updated ~every minute.
- Disk:
- *Disk Usage* (in %) per disk/mount.
- Attributes: File system type, bytes/inode total/free/used.
- Sourced via ProcFS. Updated ~every minute.
- *Total Read/Writes* (count) per disk.
- *Read/Write Rate* (in KB/s) per disk.
- Both sourced via SysFS. Updated ~every 5 seconds.
- Networking:
- *Connection State* (connected/disconnected/activating/deactivating) per
connection. Updated when state changes. Requires D-Bus and NetworkManager.
- Attributes: IP addresses and networks.
- Connected Wi-Fi Network Details (requires D-Bus and NetworkManager.):
- *SSID* (the SSID of the Wi-Fi network). Updated when SSID changes.
- *Frequency* (the frequency band of the Wi-Fi network, in Hz). Updated when frequency
changes.
- *Speed* (the network speed of the Wi-Fi network, in Mbps). Updated when speed
changes.
- *Strength* (the strength of the signal of the Wi-Fi network, in dB).
Updated when strength changes.
- *BSSID* (the BSSID of the Wi-Fi network). Updated when BSSID changes.
- *Bytes Received/Sent* (in B). Updated ~every 5s.
- Attributes: packet count, drops, errors. Via ProcFS.
- *Bytes Received/Sent Rate* (transfer rate, in B/s). Updated ~every 5
seconds. Via ProcFS.
- CPU:
- *Load Average (1/5/15 min)*. Updated ~every 1 minute. Via ProcFS.
- *CPU Usage* (in %). Updated ~every 10 seconds. Via ProcFS.
- Power Related Details:
- *Power Profile* (the current power profile as set by the
power-profiles-daemon). Updated when profile changes.
- Via D-Bus (requires [power-profiles-daemon](https://hadess.fedorapeople.org/power-profiles-daemon-docs/gdbus-net.hadess.PowerProfiles.html)).
- *Screen Lock State* (current state of screen lock). Updated when screen lock
changes.
- Via D-Bus. Requires `xscreensaver` or `systemd-logind` support.
- *Power State* (power state of device, e.g., suspended, powered on/off).
Updated when power state changes.
- Via D-Bus. Requires `systemd-logind`.
- Various System Details:
- *Boot Time* (date/Time of last system boot). Updated ~every 15 minutes. Via ProcFS.
- *Uptime*. Updated ~every 15 minutes. Via ProcFS.
- *Kernel Version* (version of the currently running kernel). Updated on agent
start. Via ProcFS.
- Distribution Details:
- *Distribution Name* (name of the running distribution, e.g., Fedora,
Ubuntu).
- *Distribution Version* (version of the running distribution).
- Both updated on agent start. Via ProcFS.
- *Current Users* (count of users with active sessions on the system). Updated
when any session changes.
- Attributes: List of usernames | When user count changes.
- Via D-Bus. Requires `systemd-logind`.
- *ABRT Problems* (count of any problems logged to the ABRT daemon). Updated
~every 15 minutes.
- Attributes: extracted problem details.
- Requires ABRT.
- Hardware Sensors:
- Any temp, fan, power and other hardware sensors, including associated
alarms. Updated ~every 1 minute.
- Extracted from the `/sys/class/hwmon` file system.
#### :robot: Script Sensors (All Platforms)
All platforms can also utilise scripts to create custom sensors. See
[scripts](#script-sensors).
#### :bus: Control via MQTT (All Platforms)
Where Home Assistant is connected to MQTT, Go Hass Agent can add some controls
for various system features. A selection of device controls are provided by
default, and you can configure additional controls to execute D-Bus commands or
scripts/executables. See [Control via MQTT](#controls-via-mqtt).
### 🤔 Use-cases
As examples of some of the things that can be done with the data published by
this app:
- Change your lighting depending on:
- What active/running apps are on your laptop/desktop. For example, you could
set your lights dim or activate a scene when you are gaming.
- Whether your screen is locked or the device is shutdown/suspended.
- With your laptop plugged into a smart plug that is also controlled by Home
Assistant, turn the smart plug on/off based on the battery charge. This can
force a full charge/discharge cycle of the battery, extending its life over
leaving it constantly charged.
- Like on mobile devices, create automations based on the location of your
laptop running this app.
- Monitor network the data transfer amount from the device, useful where network
data might be capped.
- Monitor CPU load, disk usage and any temperature sensors emitted from the
device.
- Receive notifications from Home Assistant on your desktop/laptop. Potentially
based on or utilising any of the data above.
### 🗒️ Versioning
This project follows [semantic versioning](https://semver.org/). Given a version
number `MAJOR`.`MINOR`.`PATCH`, the gist of it is:
- A `MAJOR` number change means breaking changes from the previous release.
- A `MINOR` number change means significant changes and new features have been
added, but not breaking changes.
- A `PATCH` number change indicate minor changes and bug fixes.
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- Getting Started -->
## :toolbox: Getting Started
### 🤝 Compatibility
Currently, only Linux is supported. Though the code is designed to be extensible
to other operating systems. See development information in the
[docs](docs/README.md) for details on how to extend for other operating systems.
<!-- Installation -->
### :gear: Installation
#### 📦 Packages
Head over to the [releases](https://github.com/joshuar/go-hass-agent/releases)
page and download the appropriate package for your operating system and/or
distribution:
- **Fedora**: use the `.rpm`.
- **Ubuntu**: use the `.deb`.
- **Debian**: use the `.tar.xz`.
- **Arch**: use the `.tar.zst`.
Packages (and binaries) are available for **amd64**, **arm (v7)** and **arm64**
architectures.
For distributions not listed above, you can try the binary, or build it
yourself from source (see development [docs](docs/README.md)). Note that while
Go is known for statically compiled binaries that “run anywhere”, the Fyne UI
toolkit used by Go Hass Agent makes use of shared libraries that may need to
be installed as well.
Package signatures can be verified with
[cosign](https://github.com/sigstore/cosign). To verify a package, you'll need
to download [cosign.pub](cosign.pub) public key and the `.sig` file (downloaded from
[releases](https://github.com/joshuar/go-hass-agent/releases)) that matches the
package you want to verify. To verify a package, a command similar to the
following for the `rpm` package can be used:
```shell
cosign verify-blob --key cosign.pub --signature go-hass-agent-*.rpm.sig go-hass-agent-*.rpm
```
#### 🚢 Container
Container images are available on
[ghcr.io](https://github.com/joshuar/go-hass-agent/pkgs/container/go-hass-agent).
Note that it is recommended to use an image tagged with the latest release
version over the latest container image, which might be unstable.
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- Usage -->
## :eyes: Usage
Go Hass Agent runs as a tray icon by default. It is operating system,
distribution and desktop-environment agnostic and should manifest itself in any
tray of any desktop environment.
### 🔛 First-run
On first-run, Go Hass Agent will display a window where you will need to enter
some details, so it can register itself with a Home Assistant instance to be
able to report sensors and receive notifications.
![Registration Window](assets/screenshots/registration.png)
**You will need:**
- A long-lived access token. You can generate one on your [account profile
page](https://www.home-assistant.io/docs/authentication/#your-account-profile).
- The web address (URL) on which a Home Assistant instance can be found.
- Go Hass Agent will try to auto-detect this for you, and you can select it in
the _Auto-discovered servers_ list. Otherwise, you will need to select _Use
Custom Server?_, and enter the details manually in _Manual Server Entry_.
When you have entered all the details, click **Submit** and the agent should
start running and reporting sensors to the Home Assistant instance.
### Running “Headless”
Go Hass Agent will automatically detect if there is no GUI available and run in
a “headless” mode with no UI. Registration will need to be completed manually as
a first step in such environments.
You can register Go Hass Agent on the command-line with by
running:
```shell
go-hass-agent --terminal register --token _TOKEN_ --server _URL_
```
You will need to provide a long-lived token `_TOKEN_` and the URL of your Home
Assistant instance, `_URL_`.
Once registered, running Go Hass Agent again with no options should start
tracking and sending sensor data to Home Assistant.
If desired, headless mode can be forced, even in graphical environments, by
specifying the `--terminal` command-line option.
If you want to run Go Hass Agent as a service on a headless machine, see the
[FAQ](docs/faq.md#q-i-want-to-run-the-agent-on-a-server-as-a-service-without-a-gui-can-i-do-this).
### Running in a container
There is rough support for running Go Hass Agent within a container. Pre-built
images [are available](https://github.com/joshuar/go-hass-agent/pkgs/container/go-hass-agent).
To register the agent running in a container, run the following:
```shell
podman run --rm --hostname go-hass-agent-container \
--network host \
--volume go-hass-agent:/home/ubuntu \
ghcr.io/joshuar/go-hass-agent register \
--server https://some.server:port \
--token longlivedtoken
```
Adjust the `--server` and `--token` values as appropriate.
Once registered, run the agent with:
```shell
podman run --hostname go-hass-agent-container --name my-go-hass-agent \
--network host \
--volume go-hass-agent:/home/ubuntu \
--volume /proc:/host/proc:ro --volume /sys:/host/sys:ro \
--volume /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket:ro \
--volume /run/user/1000/bus:/run/user/1000/bus:ro \
ghcr.io/joshuar/go-hass-agent # any additional options
```
Change the value passed to `--name` to a unique name for your running container
and `--hostname` for the hostname that will be presented to Home Assistant
during registration.
All the other volume mounts are optional, but functionality and the sensors
reported will be severely limited without them.
### Regular Usage
When running, Go Hass Agent will appear as a device under the Mobile App
integration in your Home Assistant instance. It should also report a list of
sensors/entities you can use in any automations, scripts, dashboards and other
parts of Home Assistant.
[![Open your Home Assistant instance to the mobile_app integration.](https://my.home-assistant.io/badges/integration.svg)](https://my.home-assistant.io/redirect/integration/?domain=mobile_app)
### Configuration Location
The configuration is located in a file called `preferences.toml` in
`CONFIG_HOME/com.github.joshuar.go-hass-agent/` where `CONFIG_HOME` will
OS-dependent:
- Linux: `~/.config`.
- OSX: `~/Library/Application Support`.
- Windows: `LocalAppData`.
While the configuration can be edited manually, it is recommended to let the
agent manage this file.
### Script Sensors
Go Hass Agent supports utilising scripts to create sensors. In this way, you can
extend the sensors presented to Home Assistant by the agent. Note that as the
agent is a “mobile app” in Home Assistant, any script sensors will be associated
with the Go Hass Agent device in Home Assistant.
Each script run by the agent can create one or more sensors and each script can
run on its own schedule, specified using a Cron syntax.
#### Requirements
- Scripts need to be put in a `scripts` folder under the configuration directory
(see [Configuration Location](#configuration-location).
- You can use symlinks, if supported by your Operating System.
- Script files need to be executable by the user running Go Hass Agent.
- Scripts need to run without any user interaction.
- Scripts need to output either valid JSON, YAML or TOML. See [Output
Format](#output-format) for details.
- Commands do not invoke the system shell and does not support expansion/glob
patterns or handle other expansions, pipelines, or redirections typically done
by shells.
#### Supported Scripting Languages
Any typical scripting language that can be invoked with a shebang can be used
for scripts. All scripts do not need to be written in the same language. So or
the typical shells can be used such as Bash, Sh, Zsh, Fish, Elvish. Scripting
languages such as Python, Perl, and Ruby can also be used.
#### Output Format
All scripts should produce output that is either valid JSON, YAML or TOML.
Scripts do not need to use the same format; you can have one script that
produces JSON and another that produces TOML. All scripts will need to output
the following fields:
- A `schedule` field containing a [cron-formatted schedule](#schedule).
- A `sensors` field containing a list of sensors.
Sensors themselves need to be represented by the following fields:
- `sensor_name`: the *friendly* name of the sensor in Home Assistant (e.g., *My
Script Sensor*).
- `sensor_icon`: a [Material Design
Icon](https://pictogrammers.github.io/@mdi/font/2.0.46/) representing the
current state. It can be changed dynamically based on the current state or
remain constant. Format is `mdi:icon_name`.
- `sensor_state`: the current value of the sensor. For numerical states, without
the units. Otherwise, a *string* or *boolean* (for binary sensors).
- **Note:** for a binary sensor, do not enclose the `true`/`false` in quotes.
The following optional fields can also be specified, which help control the
display in Home Assistant.
- `sensor_units`: the units for the state value.
- `sensor_type`: the *type* of sensor. If this is a binary sensor with a boolean
value, set this to *“binary”*. Else, do not set this field.
- `sensor_device_class`: a Home Assistant [Device
Class](https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes)
for the sensor, which will dictate how it will be displayed in Home Assistant.
There are many, pick an appropriate one (see
[`internal/hass/sensor/deviceClass.go`](../internal/hass/sensor/deviceClass.go)).
If setting `sensor_device_class`, it is likely required to set an appropriate
unit in `sensor_units` as well.
- `sensor_state_class`: the Home Assistant [State
Class](https://developers.home-assistant.io/docs/core/entity/sensor/#available-state-classes).
Either *measurement*, *total* or *total_increasing*.
- `sensor_attributes`: any additional attributes to be displayed with the
sensor. **Note that the value is required to be valid JSON, regardless of the
script output format.**
##### Examples
The following examples show a script that produces two sensors, in different
output formats.
###### JSON
JSON output can be either compressed:
```json
{"schedule":"@every 5s","sensors":[{"sensor_name": "random 1","sensor_icon": "mdi:dice-1","sensor_state":1},{"sensor_name": "random 2","sensor_icon": "mdi:dice-2","sensor_state_class":"measurement","sensor_state":6}]}
```
Or pretty-printed:
```json
{
"schedule": "@every 5s",
"sensors": [
{
"sensor_name": "random 1",
"sensor_icon": "mdi:dice-1",
"sensor_state": 2
},
{
"sensor_name": "random 2",
"sensor_icon": "mdi:dice-2",
"sensor_state_class": "measurement",
"sensor_state": 6
}
]
}
```
###### YAML
```yaml
schedule: '@every 5s'
sensors:
- sensor_name: random 1
sensor_icon: mdi:dice-1
sensor_state: 8
- sensor_name: random 2
sensor_icon: mdi:dice-2
sensor_state_class: measurement
sensor_state: 9
```
###### TOML
```toml
schedule = '@every 5s'
[[sensors]]
sensor_icon = 'mdi:dice-1'
sensor_name = 'random 1'
sensor_state = 3
[[sensors]]
sensor_icon = 'mdi:dice-2'
sensor_name = 'random 2'
sensor_state = 3
sensor_state_class = 'measurement'
```
For a binary sensor, the output should have `sensor_type` set to “binary” and
the `sensor_state` as `true` or `false` (without quotes). As an example in
compressed JSON format:
```json
{"schedule":"@every 10s","sensors":[{"sensor_name":"random 4","sensor_type":"binary","sensor_icon":"mdi:dice-3","sensor_state":false}]}
```
#### Schedule
The `schedule` field is used to specify the schedule or interval on which the
script will be run by the agent. Each script is run on its own schedule. All
sensors and their values should be returned each time the script is run. The
format is documented by the [cron Golang
package](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-CRON_Expression_Format).
In most cases, it is presumed that the script needs to be run on some interval
of time. In that case, the easiest way to specify that is with the `@every
<duration>` as per the [example output](#examples) such as:
- `@every 5s`: every 5 seconds
- `@every 1h30m`: every 1 and a half hours.
Or a pre-defined schedule:
- `@hourly`.
- `@daily`.
- `@weekly`.
- `@monthly`.
- `@yearly`.
However, more cron formats are supported:
- `"30 * * * *"`: every hour on the half hour.
- `"30 3-6,20-23 * * *"`: in the range 3-6am, 8-11pm.
- `"CRON_TZ=Asia/Tokyo 30 04 * * *"`: at 04:30 Tokyo time every day.
> [!WARNING]
> Some schedules, while supported, might not make much sense.
#### Security Implications
Running scripts can be dangerous, especially if the script does not have robust
error-handling or whose origin is untrusted or unknown. Go Hass Agent makes no
attempt to do any analysis or sanitisation of script output, other than ensuring
the output is a [supported format](#output-format). As such, ensure you trust
and understand what the script does and all possible outputs that the script can
produce. Scripts are run by the agent and have the permissions of the user
running the agent. Script output is sent to your Home Assistant instance.
### Controls (via MQTT)
> [!NOTE]
> Control via MQTT is not enabled by default.
If Home Assistant is connected to
[MQTT](https://www.home-assistant.io/integrations/mqtt/), you can also configure
Go Hass Agent to connect to MQTT, which will then expose some controls in Home
Assistant to control the device running the agent. Additionally, you can
configure your own custom controls to run either [D-Bus
commands](#custom-d-bus-controls) or [scripts and executables](#other-custom-commands).
#### Requirements
- For Linux:
- Controls rely on distribution/system support for `systemd-logind` and a working
D-Bus connection.
#### Configuration
To configure the agent to connect to MQTT:
1. Right-click on the Go Hass Agent tray icon.
2. Select *Settings→App*.
3. Toggle ***Use MQTT*** and then enter the details for your MQTT server (not
your Home Assistant server).
4. Click ***Save***.
5. Restart Go Hass Agent.
After the above steps, Go Hass Agent will appear as a device under the MQTT
integration in your Home Assistant.
[![Open your Home Assistant instance and show the MQTT integration.](https://my.home-assistant.io/badges/integration.svg)](https://my.home-assistant.io/redirect/integration/?domain=mqtt)
> [!NOTE]
> Go Hass Agent will appear in two places in your Home Assistant.
> Firstly, under the Mobile App integration, which will show all the *sensors*
> that Go Hass Agent is reporting. Secondly, under the MQTT integration, which
> will show the *controls* for Go Hass Agent. Unfortunately, due to limitations
> with the Home Assistant architecture, these cannot be combined in a single
> place.
#### Available Controls
The following table shows the controls that are available. You can add these
controls to dashboards in Home Assistant or use them in automations with a
service call.
| Control | What it does |
|--------|------------------|
| Lock Screen | Locks the session for the user running Go Hass Agent |
| Unlock Screen | Unlocks the session for the user running Go Hass Agent |
| Lock Screensaver | Lock the “screensaver” of the session for the user running Go Hass Agent |
| Suspend | Will (instantly) suspend (the system state is saved to RAM and the CPU is turned off) the device running Go Hass Agent |
| Hibernate | Will (instantly) hibernate (the system state is saved to disk and the machine is powered down) the device running Go Hass Agent |
| Power Off | Will (instantly) power off the device running Go Hass Agent |
| Reboot | Will (instantly) reboot the device running Go Hass Agent |
| Volume Control | Adjust the volume on the default audio output device |
| Volume Mute | Mute/Unmute the default audio output device |
#### Custom D-BUS Controls
The agent will subscribe to the MQTT topic `gohassagent/dbus` on the configured
MQTT broker and listens for JSON messages of the below format, which will be
accordingly dispatched to the systems
[D-Bus](https://www.freedesktop.org/wiki/Software/dbus/).
```json
{
"bus": "session",
"path": "/org/cinnamon/ScreenSaver",
"method": "org.cinnamon.ScreenSaver.Lock",
"destination": "org.cinnamon.ScreenSaver",
"args": [
""
]
}
```
This can be used to trigger arbitrary d-bus commands on the system where the
agent runs on, by using any MQTT client such as the Home Assistant
[`mqtt.publish`](https://www.home-assistant.io/integrations/mqtt/#service-mqttpublish)
service.
#### Other Custom Commands
You can optionally create a `commands.toml` file under the configuration
directory (see [Configuration Location](#configuration-location) with custom
commands to be exposed in Home Assistant.
Supported control types and expected input/output:
- [Button](https://www.home-assistant.io/integrations/button.mqtt/).
- Output is discarded. Return value is used to indicate success/failure.
> [!NOTE]
> Commands run as the user running the agent. Commands do not invoke the system
> shell and does not support expansion/glob patterns or handle other expansions,
> pipelines, or redirections typically done by shells.
Each command needs the following definition in the file:
```toml
[[control]] # where "control" is one of the control types above.
name = "my command name" # required. the pretty name of the command that will the control label in Home Assistant.
exec = "/path/to/command" # required. the path to the command to execute.
icon = "mdi:something" # optional. the material design icon to use to represent the control in Home Assistant.
```
The following shows an example that configures two buttons
in Home Assistant:
```toml
[[button]]
name = "My Command With an Icon"
exec = 'command arg1 arg2 "arg3"'
icon = "mdi:chat"
[[button]]
name = "My Command"
exec = "command"
```
#### Security Implications
There is a significant discrepancy in permissions between the device running Go
Hass Agent and Home Assistant.
Go Hass Agent runs under a user account on a device. So the above controls will
only work where that user has permissions to run the underlying actions on that
device. Home Assistant does not currently offer any fine-grained access control
for controls like the above. So any Home Assistant user will be able to run any
of the controls. This means that a Home Assistant user not associated with the
device user running the agent can use the exposed controls to issue potentially
disruptive actions on a device that another user is accessing.
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- Roadmap -->
## :compass: Roadmap
Check out [what I'm working
on](https://github.com/joshuar/go-hass-agent/discussions/150) for future
releases.
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- Contributing -->
## :wave: Contributing
- Found an issue? Please [report
it](https://github.com/joshuar/go-hass-agent/issues/new?assignees=joshuar&labels=&template=bug_report.md&title=%5BBUG%5D)!
- Have a suggestion for a feature? Want a particular sensor/measurement added?
Submit a [feature
request](https://github.com/joshuar/go-hass-agent/issues/new?assignees=joshuar&labels=&template=feature_request.md&title=)!
- Want to help develop Go Hass Agent? See the [contributing
guidelines](CONTRIBUTING.md).
<!-- Code of Conduct -->
### :scroll: Code of Conduct
Please read the [Code of Conduct](https://github.com/joshuar/go-hass-agent/blob/master/CODE_OF_CONDUCT.md)
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- FAQ -->
## :grey_question: FAQ
- _Can I change the units of the sensor?_
- Yes! In the [customisation
options](https://www.home-assistant.io/docs/configuration/customizing-devices/)
for a sensor/entity, you can change the _unit of measurement_ (and _display
precision_ if desired). This is useful for sensors whose native unit is not very
human-friendly. For example the memory sensors report values in bytes (B),
whereas you may wish to change the unit of measurement to gigabytes (GB).
- _Can I disable some sensors?_
- The agent itself does not currently support disabling individual sensors.
However, you can disable the corresponding sensor entity in Home Assistant,
and the agent will stop sending updates for it.
- To disable a sensor entity, In the [customisation
options](https://www.home-assistant.io/docs/configuration/customizing-devices/)
for a sensor/entity, toggle the *Enabled* switch. The agent will automatically
detect the disabled state and send/not send updates as appropriate.
- Note that while the agent will stop sending updates for a disabled sensor,
it will not stop gathering the raw data for the sensor.
- _The GUI windows are too small/too big. How can I change the size?_
- See [Scaling](https://developer.fyne.io/architecture/scaling) in the Fyne
documentation. In the tray icon menu, select _Settings_ to open the Fyne
settings app which can adjust the scaling for the app windows.
- _What is the resource (CPU, memory) usage of the agent?_
- Very little in most cases. On Linux, the agent with all sensors working, should
consume well less than 50 MB of memory with very little CPU usage. Further
memory savings can be achieved by running the agent in “headless” mode with the
`--terminal` command-line option. This should put the memory usage below 25 MB.
- On Linux, many sensors rely on D-Bus signals for publishing their data, so
CPU usage may be affected by the “business” of the bus. For sensors that are
polled on an interval, the agent makes use of some jitter in the polling
intervals to avoid a “thundering herd” problem.
- _I've updated the agent and now some sensors have been renamed. I now have a
bunch of sensors/entities in Home Assistant I want to remove. What can I do?_
- Unfortunately, sometimes the sensor naming scheme for some sensors created
by the agent needs to change. There is unfortunately, no way for the agent to
rename existing sensors in Home Assistant, so you end up with both the old and
new sensors showing, and only the new sensors updating.
- You can remove the old sensors manually, under Developer Tools→Statistics in
Home Assistant, for example. The list should contain sensors that are no longer
“provided” by the agent. Or you can wait until they age out of the Home
Assistant long-term statistics database automatically.
- _Can I reset the agent (start from new)?_
- Yes. You can reset the agent so that it will re-register with Home Assistant
and act as a new device. To do this:
1. Shut down the agent if it is running.
2. In Home Assistant, navigate to **Settings→Devices & Services** and click
on the **Mobile App** integration.
3. Locate the agent entry in the list of mobile devices, click the context menu
(three vertical dots), and choose **_Delete_**.
4. From a terminal, run the agent with the command: `go-hass-agent register
--force` (add `--terminal --server someserver --token sometoken` for
non-graphical registration).
5. The agent will go through the initial registration steps. It should report
that registration was successful.
6. Restart the agent.
- _I want to run the agent on a server, as a service, without a GUI. Can I do
this?_
- Yes. The packages install a systemd service file that can be enabled and
used to run the agent as a service.
- You will still need to register the agent manually before starting as a service.
See the command for registration in the [README](#running-headless).
- You will also need to ensure your user has “lingering” enabled. Run `loginctl
list-users` and check that your user has **LINGER** set to “yes”. If not, run
`loginctl enable-linger`.
- Once you have registered the agent and enabled lingering for your user. Enable
the service and start it with the command: `systemctl --user enable
go-hass-agent && systemctl --user start go-hass-agent`.
- You can check the status with `systemctl --user status go-hass-agent`. The agent
should start with every boot.
- For other init systems, consult their documentation on how to enable and run
user services.
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- Acknowledgments -->
## :gem: Acknowledgements
- [Home Assistant](https://home-assistant.io).
- This [Awesome README Template](https://github.com/Louis3797/awesome-readme-template).
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)
<!-- License -->
## :warning: License
[MIT](LICENSE)
[:arrow_up: Back to Top](#notebook_with_decorative_cover-table-of-contents)