# SwitchBot Actions: A YAML-based Automation Engine
A powerful, configurable automation engine for SwitchBot BLE devices, with an optional Prometheus exporter.
This application continuously scans for SwitchBot Bluetooth Low Energy (BLE) devices and provides a powerful automation engine that can:
- **React to Events**: Trigger custom actions (like shell commands or webhooks) the moment a device's state changes.
- **Monitor Sustained States**: Trigger actions when a device remains in a specific state for a continuous duration.
It also includes an optional **Prometheus Exporter** to expose sensor data (temperature, humidity, etc.) and device state as Prometheus metrics.
Inspired by services like GitHub Actions, all behavior is controlled through a single `config.yaml` file, allowing you to define flexible and powerful automation workflows without any code changes.
## Features
- **Real-time Monitoring**: Gathers data from all nearby SwitchBot devices.
- **Prometheus Integration**: Exposes metrics at a configurable `/metrics` endpoint.
- **Powerful Automation**: Define rules to trigger actions based on state changes (`actions`) or sustained states (`timers`).
- **Flexible Conditions**: Build rules based on device model, address, sensor values, and even signal strength (`rssi`).
- **Highly Configurable**: Filter devices, select metrics, and define complex rules from a single configuration file.
- **Extensible Architecture**: Built on a clean, decoupled architecture, making it easy to extend.
## Getting Started
### Prerequisites
* Python 3.10+
* A Linux-based system with a Bluetooth adapter that supports BLE (e.g., Raspberry Pi).
### Installation (Recommended using pipx)
For command-line applications like this, we strongly recommend installing with `pipx` to keep your system clean and avoid dependency conflicts.
1. **Install pipx:**
```bash
pip install pipx
pipx ensurepath
```
*(You may need to restart your terminal after this step for the path changes to take effect.)*
2. **Install the application:**
```bash
pipx install switchbot-actions
```
3. **Create your configuration file:**
Download the example configuration from the GitHub repository to get started.
```bash
curl -o config.yaml https://raw.githubusercontent.com/hnw/switchbot-actions/main/config.yaml.example
```
Then, edit `config.yaml` to suit your needs.
### Alternative Installation (using pip)
If you prefer to manage your environments manually, you can use `pip`. It is recommended to do this within a virtual environment (`venv`).
```bash
# This command installs the package.
# To avoid polluting your global packages, consider running this in a venv.
pip install switchbot-actions
```
## Usage
We recommend a two-step process to get started smoothly.
### Step 1: Verify Hardware and Device Discovery
First, run the application without any configuration file to confirm that your Bluetooth adapter is working and can discover your SwitchBot devices.
```bash
switchbot-actions --debug
```
The `--debug` flag will show detailed logs. If you see lines containing "Received advertisement from...", your hardware setup is correct.
> [\!IMPORTANT]
> **A Note on Permissions on Linux**
>
> If you encounter errors related to "permission denied," you may need to run the command with `sudo`:
>
> ```bash
> sudo switchbot-actions --debug
> ```
### Step 2: Configure and Run
Once you've confirmed that device discovery is working, create your `config.yaml` file. You can use the example as a starting point:
```bash
curl -o config.yaml https://raw.githubusercontent.com/hnw/switchbot-actions/main/config.yaml.example
```
Edit `config.yaml` to define your automations. Then, run the application normally:
```bash
switchbot-actions -c config.yaml
```
## Configuration
The application is controlled by `config.yaml`. See `config.yaml.example` for a full list of options.
> [!NOTE]
> This section provides a quick overview. For a detailed and complete reference of all configuration options, please see the [**Project Specification**](./docs/specification.md#4-configuration-configyaml).
### Command-Line Options
- `--config <path>` or `-c <path>`: Specifies the path to the configuration file (default: `config.yaml`).
- `--debug` or `-d`: Enables `DEBUG` level logging, overriding any setting in the config file. This is useful for temporary troubleshooting.
- `--scan-cycle <seconds>`: Overrides the scan cycle time.
- `--scan-duration <seconds>`: Overrides the scan duration time.
- `--interface <device>`: Overrides the Bluetooth interface (e.g., `hci1`).
### Scanner (`scanner`)
Configure the behavior of the Bluetooth (BLE) scanner.
```yaml
scanner:
# Time in seconds between the start of each scan cycle.
cycle: 10
# Time in seconds the scanner will actively listen for devices.
# Must be less than or equal to `cycle`.
duration: 3
# Bluetooth interface to use.
interface: "hci0"
```
### Event-Driven Actions (`actions`)
Trigger an action **the moment** a device's state changes to meet the specified conditions (edge-triggered). The action will only fire once and will not fire again until the conditions have first become false and then true again.
In the `state` conditions, you can use the following operators for comparison: `>` (greater than), `<` (less than), `>=` (greater/equal), `<=` (less/equal), `==` (equal), and `!=` (not equal).
```yaml
actions:
- name: "High Temperature Alert"
# Cooldown for 10 minutes to prevent repeated alerts
cooldown: "10m" # Supports formats like "5s", "10m", "1.5h"
conditions:
device:
modelName: "Meter"
state:
# Triggers the moment temperature becomes greater than 28.0
temperature: "> 28.0"
trigger:
type: "webhook"
url: "https://example.com/alert"
payload:
message: "High temperature detected: {temperature}°C"
# Optional: Add custom headers for APIs that require them
headers:
Authorization: "Bearer YOUR_API_KEY"
X-Custom-Header: "Value for {address}"
- name: "Weak Signal Notification"
conditions:
device:
address: "XX:XX:XX:XX:XX:AA"
state:
# Triggers if the signal strength is weaker (more negative) than -80 dBm
rssi: "< -80"
trigger:
type: "shell_command"
command: "echo 'Device {address} has a weak signal (RSSI: {rssi})'"
```
> [!NOTE]
> You can use placeholders in `command`, `url`, `payload`, and `headers`. Available placeholders include `{address}`, `{modelName}`, `{rssi}`, and any sensor value found in the device's data (e.g., `{temperature}`, `{humidity}`, `{isOn}`).
### Time-Driven Timers (`timers`)
Trigger an action when a device has been in a specific state for a **continuous duration** (one-shot). Once the timer fires, it will not restart until the conditions have first become false and then true again.
```yaml
timers:
- name: "Turn off Lights if No Motion"
conditions:
device:
modelName: "WoPresence"
state:
# The state that must be true for the whole duration
motion_detected: False
# The duration the state must be sustained
duration: "5m"
trigger:
type: "shell_command"
command: "echo 'No motion for 5 minutes, turning off lights.'"
- name: "Alert if Door is Left Open"
conditions:
device:
modelName: "WoContact"
state:
contact_open: True
duration: "10m"
trigger:
type: "webhook"
url: "https://example.com/alert"
payload:
message: "Warning: Door {address} has been open for 10 minutes!"
```
### Prometheus Exporter (`prometheus_exporter`)
This feature exposes all collected SwitchBot device data as Prometheus metrics, allowing for powerful monitoring and visualization. Once enabled, metrics will be available at the `/metrics` endpoint (e.g., `http://localhost:8000/metrics`). You can scrape this endpoint with a Prometheus server and use tools like Grafana to create dashboards for temperature, humidity, battery levels, and more.
```yaml
prometheus_exporter:
enabled: true
port: 8000
target:
# Optional: Only export metrics for these MAC addresses
addresses:
- "XX:XX:XX:XX:XX:AA"
# Optional: Only export these specific metrics
metrics:
- "temperature"
- "humidity"
- "battery"
- "rssi"
```
### Logging (`logging`)
Configure the log output format and verbosity. This allows for fine-grained control over log output for both the application and its underlying libraries.
```yaml
logging:
# Default log level for the application: DEBUG, INFO, WARNING, ERROR
level: "INFO"
# Log format using Python's logging syntax
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Set specific log levels for noisy libraries.
# This is useful for debugging specific components without enabling global debug.
loggers:
bleak: "WARNING" # Can be set to DEBUG for deep BLE troubleshooting
# aiohttp: "WARNING"
```
#### Debugging Notes
- **For Application Development (`--debug` flag):**
When you run the exporter with `--debug` or `-d`, the `logging` section in your `config.yaml` is **ignored**. This flag is a shortcut that:
1. Sets the log level for `switchbot-actions` to `DEBUG`.
2. Sets the log level for the `bleak` library to `INFO` to keep the output clean.
- **For Library Troubleshooting (e.g., `bleak`):**
If you need to see `DEBUG` messages from a specific library like `bleak`, do **not** use the `--debug` flag. Instead, edit `config.yaml` and set the desired level in the `loggers` section:
```yaml
logging:
level: "INFO" # Keep the main app quiet
loggers:
bleak: "DEBUG" # Enable detailed output only for bleak
```
- **Troubleshooting Actions and Timers:**
By default, the execution of `actions` and `timers` is not logged to `INFO` to avoid excessive noise. If you need to verify that your triggers are running, enable `DEBUG` logging for the triggers module in `config.yaml`:
```yaml
logging:
level: "INFO"
loggers:
switchbot_actions.triggers: "DEBUG"
```
Raw data
{
"_id": null,
"home_page": null,
"name": "switchbot-actions",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "switchbot, automation, prometheus, ble, home-automation",
"author": null,
"author_email": "Yoshio HANAWA <y@hnw.jp>",
"download_url": "https://files.pythonhosted.org/packages/bb/42/759bf9f55cfce915b3f9eaf8b18775228828f5fa75515e5a2c1b5814e556/switchbot_actions-1.0.2.tar.gz",
"platform": null,
"description": "# SwitchBot Actions: A YAML-based Automation Engine\n\nA powerful, configurable automation engine for SwitchBot BLE devices, with an optional Prometheus exporter.\n\nThis application continuously scans for SwitchBot Bluetooth Low Energy (BLE) devices and provides a powerful automation engine that can:\n\n- **React to Events**: Trigger custom actions (like shell commands or webhooks) the moment a device's state changes.\n- **Monitor Sustained States**: Trigger actions when a device remains in a specific state for a continuous duration.\n\nIt also includes an optional **Prometheus Exporter** to expose sensor data (temperature, humidity, etc.) and device state as Prometheus metrics.\n\nInspired by services like GitHub Actions, all behavior is controlled through a single `config.yaml` file, allowing you to define flexible and powerful automation workflows without any code changes.\n\n## Features\n\n- **Real-time Monitoring**: Gathers data from all nearby SwitchBot devices.\n- **Prometheus Integration**: Exposes metrics at a configurable `/metrics` endpoint.\n- **Powerful Automation**: Define rules to trigger actions based on state changes (`actions`) or sustained states (`timers`).\n- **Flexible Conditions**: Build rules based on device model, address, sensor values, and even signal strength (`rssi`).\n- **Highly Configurable**: Filter devices, select metrics, and define complex rules from a single configuration file.\n- **Extensible Architecture**: Built on a clean, decoupled architecture, making it easy to extend.\n\n## Getting Started\n\n### Prerequisites\n\n * Python 3.10+\n * A Linux-based system with a Bluetooth adapter that supports BLE (e.g., Raspberry Pi).\n\n### Installation (Recommended using pipx)\n\nFor command-line applications like this, we strongly recommend installing with `pipx` to keep your system clean and avoid dependency conflicts.\n\n1. **Install pipx:**\n\n ```bash\n pip install pipx\n pipx ensurepath\n ```\n\n *(You may need to restart your terminal after this step for the path changes to take effect.)*\n\n2. **Install the application:**\n\n ```bash\n pipx install switchbot-actions\n ```\n\n3. **Create your configuration file:**\n Download the example configuration from the GitHub repository to get started.\n\n ```bash\n curl -o config.yaml https://raw.githubusercontent.com/hnw/switchbot-actions/main/config.yaml.example\n ```\n\n Then, edit `config.yaml` to suit your needs.\n\n### Alternative Installation (using pip)\n\nIf you prefer to manage your environments manually, you can use `pip`. It is recommended to do this within a virtual environment (`venv`).\n\n```bash\n# This command installs the package.\n# To avoid polluting your global packages, consider running this in a venv.\npip install switchbot-actions\n```\n\n## Usage\n\nWe recommend a two-step process to get started smoothly.\n\n### Step 1: Verify Hardware and Device Discovery\n\nFirst, run the application without any configuration file to confirm that your Bluetooth adapter is working and can discover your SwitchBot devices.\n\n```bash\nswitchbot-actions --debug\n```\n\nThe `--debug` flag will show detailed logs. If you see lines containing \"Received advertisement from...\", your hardware setup is correct.\n\n> [\\!IMPORTANT]\n> **A Note on Permissions on Linux**\n>\n> If you encounter errors related to \"permission denied,\" you may need to run the command with `sudo`:\n>\n> ```bash\n> sudo switchbot-actions --debug\n> ```\n\n### Step 2: Configure and Run\n\nOnce you've confirmed that device discovery is working, create your `config.yaml` file. You can use the example as a starting point:\n\n```bash\ncurl -o config.yaml https://raw.githubusercontent.com/hnw/switchbot-actions/main/config.yaml.example\n```\n\nEdit `config.yaml` to define your automations. Then, run the application normally:\n\n```bash\nswitchbot-actions -c config.yaml\n```\n\n## Configuration\n\nThe application is controlled by `config.yaml`. See `config.yaml.example` for a full list of options.\n\n> [!NOTE]\n> This section provides a quick overview. For a detailed and complete reference of all configuration options, please see the [**Project Specification**](./docs/specification.md#4-configuration-configyaml).\n\n### Command-Line Options\n\n- `--config <path>` or `-c <path>`: Specifies the path to the configuration file (default: `config.yaml`).\n- `--debug` or `-d`: Enables `DEBUG` level logging, overriding any setting in the config file. This is useful for temporary troubleshooting.\n- `--scan-cycle <seconds>`: Overrides the scan cycle time.\n- `--scan-duration <seconds>`: Overrides the scan duration time.\n- `--interface <device>`: Overrides the Bluetooth interface (e.g., `hci1`).\n\n### Scanner (`scanner`)\n\nConfigure the behavior of the Bluetooth (BLE) scanner.\n\n```yaml\nscanner:\n # Time in seconds between the start of each scan cycle.\n cycle: 10\n # Time in seconds the scanner will actively listen for devices.\n # Must be less than or equal to `cycle`.\n duration: 3\n # Bluetooth interface to use.\n interface: \"hci0\"\n```\n\n### Event-Driven Actions (`actions`)\n\nTrigger an action **the moment** a device's state changes to meet the specified conditions (edge-triggered). The action will only fire once and will not fire again until the conditions have first become false and then true again.\n\nIn the `state` conditions, you can use the following operators for comparison: `>` (greater than), `<` (less than), `>=` (greater/equal), `<=` (less/equal), `==` (equal), and `!=` (not equal).\n\n```yaml\nactions:\n - name: \"High Temperature Alert\"\n # Cooldown for 10 minutes to prevent repeated alerts\n cooldown: \"10m\" # Supports formats like \"5s\", \"10m\", \"1.5h\"\n conditions:\n device:\n modelName: \"Meter\"\n state:\n # Triggers the moment temperature becomes greater than 28.0\n temperature: \"> 28.0\"\n trigger:\n type: \"webhook\"\n url: \"https://example.com/alert\"\n payload:\n message: \"High temperature detected: {temperature}\u00b0C\"\n # Optional: Add custom headers for APIs that require them\n headers:\n Authorization: \"Bearer YOUR_API_KEY\"\n X-Custom-Header: \"Value for {address}\"\n\n - name: \"Weak Signal Notification\"\n conditions:\n device:\n address: \"XX:XX:XX:XX:XX:AA\"\n state:\n # Triggers if the signal strength is weaker (more negative) than -80 dBm\n rssi: \"< -80\"\n trigger:\n type: \"shell_command\"\n command: \"echo 'Device {address} has a weak signal (RSSI: {rssi})'\"\n```\n\n> [!NOTE]\n> You can use placeholders in `command`, `url`, `payload`, and `headers`. Available placeholders include `{address}`, `{modelName}`, `{rssi}`, and any sensor value found in the device's data (e.g., `{temperature}`, `{humidity}`, `{isOn}`).\n\n### Time-Driven Timers (`timers`)\n\nTrigger an action when a device has been in a specific state for a **continuous duration** (one-shot). Once the timer fires, it will not restart until the conditions have first become false and then true again.\n\n```yaml\ntimers:\n - name: \"Turn off Lights if No Motion\"\n conditions:\n device:\n modelName: \"WoPresence\"\n state:\n # The state that must be true for the whole duration\n motion_detected: False\n # The duration the state must be sustained\n duration: \"5m\"\n trigger:\n type: \"shell_command\"\n command: \"echo 'No motion for 5 minutes, turning off lights.'\"\n\n - name: \"Alert if Door is Left Open\"\n conditions:\n device:\n modelName: \"WoContact\"\n state:\n contact_open: True\n duration: \"10m\"\n trigger:\n type: \"webhook\"\n url: \"https://example.com/alert\"\n payload:\n message: \"Warning: Door {address} has been open for 10 minutes!\"\n```\n\n### Prometheus Exporter (`prometheus_exporter`)\n\nThis feature exposes all collected SwitchBot device data as Prometheus metrics, allowing for powerful monitoring and visualization. Once enabled, metrics will be available at the `/metrics` endpoint (e.g., `http://localhost:8000/metrics`). You can scrape this endpoint with a Prometheus server and use tools like Grafana to create dashboards for temperature, humidity, battery levels, and more.\n\n```yaml\nprometheus_exporter:\n enabled: true\n port: 8000\n target:\n # Optional: Only export metrics for these MAC addresses\n addresses:\n - \"XX:XX:XX:XX:XX:AA\"\n # Optional: Only export these specific metrics\n metrics:\n - \"temperature\"\n - \"humidity\"\n - \"battery\"\n - \"rssi\"\n```\n\n### Logging (`logging`)\n\nConfigure the log output format and verbosity. This allows for fine-grained control over log output for both the application and its underlying libraries.\n\n```yaml\nlogging:\n # Default log level for the application: DEBUG, INFO, WARNING, ERROR\n level: \"INFO\"\n\n # Log format using Python's logging syntax\n format: \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\"\n\n # Set specific log levels for noisy libraries.\n # This is useful for debugging specific components without enabling global debug.\n loggers:\n bleak: \"WARNING\" # Can be set to DEBUG for deep BLE troubleshooting\n # aiohttp: \"WARNING\"\n```\n\n#### Debugging Notes\n\n- **For Application Development (`--debug` flag):**\n When you run the exporter with `--debug` or `-d`, the `logging` section in your `config.yaml` is **ignored**. This flag is a shortcut that:\n 1. Sets the log level for `switchbot-actions` to `DEBUG`.\n 2. Sets the log level for the `bleak` library to `INFO` to keep the output clean.\n\n- **For Library Troubleshooting (e.g., `bleak`):**\n If you need to see `DEBUG` messages from a specific library like `bleak`, do **not** use the `--debug` flag. Instead, edit `config.yaml` and set the desired level in the `loggers` section:\n ```yaml\n logging:\n level: \"INFO\" # Keep the main app quiet\n loggers:\n bleak: \"DEBUG\" # Enable detailed output only for bleak\n ```\n\n- **Troubleshooting Actions and Timers:**\n By default, the execution of `actions` and `timers` is not logged to `INFO` to avoid excessive noise. If you need to verify that your triggers are running, enable `DEBUG` logging for the triggers module in `config.yaml`:\n ```yaml\n logging:\n level: \"INFO\"\n loggers:\n switchbot_actions.triggers: \"DEBUG\"\n ```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A YAML-based automation engine for SwitchBot BLE devices with a Prometheus exporter.",
"version": "1.0.2",
"project_urls": {
"Bug Tracker": "https://github.com/hnw/switchbot-actions/issues",
"Homepage": "https://github.com/hnw/switchbot-actions",
"Repository": "https://github.com/hnw/switchbot-actions"
},
"split_keywords": [
"switchbot",
" automation",
" prometheus",
" ble",
" home-automation"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "e86d7c70154ca9ff43ef13691959d4c587c7c1ecbf4ac9ffe3911345922c1f14",
"md5": "656f3299d7ff5d2f2b7cfe55fc919f60",
"sha256": "e56be294cb0b25425ff2ff90b77db16a2115b792f334305dc19ca28f9d4a41ae"
},
"downloads": -1,
"filename": "switchbot_actions-1.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "656f3299d7ff5d2f2b7cfe55fc919f60",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 17983,
"upload_time": "2025-07-13T16:10:48",
"upload_time_iso_8601": "2025-07-13T16:10:48.936024Z",
"url": "https://files.pythonhosted.org/packages/e8/6d/7c70154ca9ff43ef13691959d4c587c7c1ecbf4ac9ffe3911345922c1f14/switchbot_actions-1.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "bb42759bf9f55cfce915b3f9eaf8b18775228828f5fa75515e5a2c1b5814e556",
"md5": "ceb9b2eeef80033af5b68804ffa8e027",
"sha256": "e5313ff6df91d1237dc7326b178bf9ff87e1e0ba5e4f9c601ea129a12552dfab"
},
"downloads": -1,
"filename": "switchbot_actions-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "ceb9b2eeef80033af5b68804ffa8e027",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 24950,
"upload_time": "2025-07-13T16:10:50",
"upload_time_iso_8601": "2025-07-13T16:10:50.519141Z",
"url": "https://files.pythonhosted.org/packages/bb/42/759bf9f55cfce915b3f9eaf8b18775228828f5fa75515e5a2c1b5814e556/switchbot_actions-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-13 16:10:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hnw",
"github_project": "switchbot-actions",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "switchbot-actions"
}