Home Assistant custom integration for Terma MOA Blue electric heating elements via Bluetooth Low Energy (BLE).
This integration allows you to control Terma MOA Blue bathroom radiator heating elements directly from Home Assistant without requiring the official Terma BlueLine Next mobile app.
✅ Full Control
- Turn heating on/off
- Set target temperature (30-60°C for element, 15-30°C for room)
- Real-time temperature monitoring
- LED temperature indicator support
✅ Native Home Assistant Integration
- Climate entity for easy control
- Temperature sensor entities
- Lovelace thermostat card compatible
- Automation support
✅ Reliable Bluetooth Communication
- Automatic device discovery
- Multiple retry attempts for stable connection
- Proper BLE pairing support
- Works with Bluetooth adapters and ESPHome Bluetooth proxies
- Terma MOA Blue electric heating elements (models with Bluetooth)
- Firmware: Tested with devices from 2023-2024
- Home Assistant 2024.1.0 or newer
- Bluetooth adapter with BLE support OR ESPHome Bluetooth proxy
- Python 3.11+
- Open HACS in Home Assistant
- Go to "Integrations"
- Click the three dots (⋮) in the top right
- Select "Custom repositories"
- Add repository URL:
https://github.com/johnfromul/terma_moa_blue - Category:
Integration - Click "Add"
- Click "Install" on the Terma MOA Blue integration
- Restart Home Assistant
- Download the latest release
- Extract the
terma_moa_bluefolder to yourcustom_componentsdirectory:config/ └── custom_components/ └── terma_moa_blue/ ├── __init__.py ├── manifest.json ├── ... - Restart Home Assistant
Important: Terma MOA Blue devices require Bluetooth pairing before use.
- Press and hold the button on the heating element for 5 seconds
- The blue LED will start blinking (pairing mode active for 30 seconds)
# Open Home Assistant terminal (SSH or Terminal & SSH add-on)
bluetoothctl
# Disable scanning to stop log spam
scan off
# Pair with your device (replace with your MAC address)
pair CC:22:37:11:47:6D
# Enter PIN when prompted
123456
# Trust the device
trust CC:22:37:11:47:6D
# Verify pairing
paired-devices
# Exit
quitmake a easy bash script \config\terma_pair.sh with this code:
#!/bin/bash
# Switch the heating element into pairing mode!
echo "!!! SWITCH THE HEATING ELEMENT INTO PAIRING MODE (5s hold button with temp. icon, blue
LED slow blink) !!!"
echo "You have 30 seconds..."
sleep 10
{
sleep 2
echo "agent KeyboardDisplay"
sleep 1
echo "default-agent"
sleep 1
echo "pair CC:22:37:11:48:0D"
sleep 3
echo "123456"
sleep 5
echo "trust CC:22:37:11:48:0D"
sleep 2
echo "quit"
} | bluetoothctl
EOFha core restart- Go to Settings → Devices & Services
- Click + Add Integration
- Search for "Terma MOA Blue"
- Select your heating element from the discovered devices
- Click Submit
The integration will create:
- 1 Climate entity (thermostat)
- 2 Temperature sensor entities (current room, current element)
Add a thermostat card to your dashboard:
type: thermostat
entity: climate.terma_wireless_elementTurn on heating:
service: climate.set_hvac_mode
target:
entity_id: climate.terma_wireless_element
data:
hvac_mode: heatSet temperature:
service: climate.set_temperature
target:
entity_id: climate.terma_wireless_element
data:
temperature: 50Turn off:
service: climate.set_hvac_mode
target:
entity_id: climate.terma_wireless_element
data:
hvac_mode: "off"Heat bathroom before morning shower:
automation:
- alias: "Morning Bathroom Heat"
trigger:
- platform: time
at: "06:00:00"
action:
- service: climate.set_hvac_mode
target:
entity_id: climate.terma_wireless_element
data:
hvac_mode: heat
- service: climate.set_temperature
target:
entity_id: climate.terma_wireless_element
data:
temperature: 55
- delay:
minutes: 30
- service: climate.set_hvac_mode
target:
entity_id: climate.terma_wireless_element
data:
hvac_mode: "off"- Element Temperature: 30-60°C (radiator heating element)
- Room Temperature: 15-30°C (ambient room temperature)
The integration polls the device every 120 seconds (2 minutes) to preserve battery life and BLE connection stability.
The heating element's LED bars indicate the current target temperature:
- 1 bar: 30-37°C
- 2 bars: 38-43°C
- 3 bars: 44-49°C
- 4 bars: 50-55°C
- 5 bars: 56-60°C
- Check Bluetooth range: Ensure heating element is within range of your Bluetooth adapter
- Put device in pairing mode: Blue LED should be blinking
- Check logs: Settings → System → Logs, filter by
terma_moa_blue
Error: failed to discover services, device disconnected
Solution: Device is not paired. Follow the Bluetooth pairing steps above.
Error: ATT error: 0x0e (Unlikely Error)
Solution: Authentication failed. Remove old pairing and pair again:
bluetoothctl
remove CC:22:37:11:47:6D
# Then follow pairing steps again- Verify device is powered (connected to mains)
- Check wattmeter: should show ~600W when heating
- Enable debug logging (see below)
- Check that heating mode is set correctly
Enable detailed logging in configuration.yaml:
logger:
default: info
logs:
custom_components.terma_moa_blue: debugRestart Home Assistant and check the logs.
This integration was developed through reverse engineering of the Terma BlueLine Next mobile app using Frida instrumentation.
Key findings:
- Device uses Bluetooth Low Energy (BLE) GATT protocol
- Service UUID:
d97352b0-d19e-11e2-9e96-0800200c9a66 - Operating modes:
0x20(OFF),0x21(ON) - Temperature format: Little-endian 16-bit integer (value × 10)
- Requires Bluetooth pairing with PIN
123456
| UUID | Function | Format |
|---|---|---|
d97352b1 |
Room temperature | [current_low, current_high, target_low, target_high] |
d97352b2 |
Element temperature | [current_low, current_high, target_low, target_high] |
d97352b3 |
Operating mode | [mode, 0x00, 0x00, 0x00] |
custom_components/terma_moa_blue/
├── __init__.py # Integration setup
├── manifest.json # Integration metadata
├── config_flow.py # Configuration flow
├── const.py # Constants and enums
├── coordinator.py # Data update coordinator
├── api.py # BLE communication layer
├── climate.py # Climate entity
└── sensor.py # Sensor entities
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
The protocol was reverse-engineered using:
- Frida instrumentation framework
- Android app decompilation (JADX)
- BLE packet capture (Wireshark)
- Runtime hooking of Bluetooth GATT operations
See Frida scripts for details.
- Developer: @johnfromul
- Assistant: Claude (Anthropic) - Protocol analysis and integration development
- Manufacturer: Terma
MIT License - see LICENSE file for details.
This is an unofficial integration not affiliated with or endorsed by Terma. Use at your own risk.
The integration was developed through reverse engineering for personal use and educational purposes. All trademarks belong to their respective owners.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
See CHANGELOG.md for version history.
- Home Assistant
- HACS
- Bleak - BLE library
- ESPHome Bluetooth Proxy
⭐ If you find this integration useful, please star the repository!