Sending Room Temperature Data from HA into Controme (Virtual Sensor Injection)

I wanted a reliable way to inject room temperature values from Home Assistant into my Controme Smart‑Heat system, so Controme can work with the same temperature readings that HA receives from sensors not directly part of the heating system. This turned out especially useful in rooms with strong temperature gradients, where a second measurement point gives Controme a more accurate picture.

Controme offers Virtual Sensors for exactly this purpose, but their REST API does not provide an official “write virtual sensor” endpoint.
So in this post I’m sharing a clean method to send temperature values into Controme anyway.

For context: I’ve had Controme since 2017, I’m very happy with it, and with help from the community (thanks @4flames) I integrated it first into openHAB and later into Home Assistant.


Prerequisite: You need to have purchased a Controme Virtual Sensor for this to work.


:exclamation: What Controme’s API cannot do

The Controme REST API provides a well‑documented GET interface for reading temperatures and room values.
But it does not include a POST/PUT method for sending virtual sensor data.


:heavy_check_mark: What does work

Each Controme sensor (including virtual ones) has an internal ID such as:

28_ff_12_34_56_ab_cd_ef

If you send a value directly to that ID using:

http://<CONTROME_IP>/set/<SENSOR_ID>/<VALUE>/

…Controme accepts it as a sensor update.

You could overwrite physical sensors this way . whyever. Better use virtual sensors, which Controme designed specifically for injecting your own data.


:jigsaw: The odd part: Controme only accepts certain decimal fractions

From testing, Controme accepts a 16‑step decimal lattice per degree. The allowed fractional parts are:

0.00, 0.06, 0.12, 0.19,
0.25, 0.31, 0.38, 0.44,
0.50, 0.56, 0.62, 0.69,
0.75, 0.81, 0.88, 0.94

If you send any other decimal values, Controme ignores them.
So in HA you should snap (quantize) your room temperature to the nearest of these steps before sending.


:stopwatch: Intervals that worked best for me

I experimented with 1, 3, and 5‑minute intervals.
1 minute gave me the most consistent results.
I did not test shorter intervals; they felt excessive given Controme’s normal control cadence—but I might be wrong, so feel free to try shorter cycles if you have a use case.


:blue_square: Clean HA Method: Snap in HA → Send via simple curl

1) (Optional) Helper number for testing**

input_number:
  controme_temp_raw:
    name: "Controme Raw Temp"
    min: -20
    max: 50
    step: 0.01
    unit_of_measurement: "°C"

2) Create a snapped (quantized) temperature with new‑style template: syntax**


template:
  - sensor:
      - name: "Controme Temp Snapped"
        unique_id: controme_temp_snapped
        device_class: temperature
        state_class: measurement
        unit_of_measurement: "°C"
        state: >
          {% set raw = states('input_number.controme_temp_raw') | float %}
          {% set base = raw | int %}
          {% set decimal = raw - base %}
          {% set allowed = [0.00, 0.06, 0.12, 0.19, 0.25, 0.31, 0.38, 0.44,
                            0.50, 0.56, 0.62, 0.69, 0.75, 0.81, 0.88, 0.94] %}

          {% set ns = namespace(closest=allowed[0],
                                min_diff=((decimal - allowed[0]) | abs)) %}
          {% for a in allowed[1:] %}
            {% set diff = (decimal - a) | abs %}
            {% if diff < ns.min_diff %}
              {% set ns.closest = a %}
              {% set ns.min_diff = diff %}
            {% endif %}
          {% endfor %}

          {{ "%.2f" | format(base + ns.closest) }}

Replace input_number.controme_temp_raw with your actual room temperature entity when you move from testing to production.

3) Where and how to place** the shell_command (and a secrets‑friendly variant)

You define shell_command in configuration.yaml (top‑level).
If you already use !include files, place it in your chosen include file and reference it from configuration.yaml.

A. Simple in‑place definition (clean & minimal):

# configuration.yaml
shell_command:
  controme_write_virtual_sensor: >
    curl -s -S -L -X GET
    "http://<CONTROME_IP>/set/<SENSOR_ID>/{{ value }}/"
  • Replace <CONTROME_IP> with your Mini‑Server IP.
  • Replace <SENSOR_ID> with your virtual sensor’s ID.
  • The {{ value }} is the snapped "%.2f" string you’ll pass from the script/automation.

B. Secrets‑friendly variant (recommended if you need auth on write):

# configuration.yaml
shell_command:
  controme_write_virtual_sensor_auth: >
    curl -s -S -L -G "http://<CONTROME_IP>/set/<SENSOR_ID>/{{ value }}/"
    --data-urlencode "user=!secret controme_user"
    --data-urlencode "password=!secret controme_password"

…and in secrets.yaml:

controme_user: [email protected]
controme_password: yourStrongPassword123!

After adding/modifying shell_command, go to Developer Tools → YAML → Reload Command Line (or restart HA).
If you use a separate include (e.g., shell_command.yaml), ensure configuration.yaml contains shell_command: !include shell_command.yaml.


4) Script to push the snapped value every minute

script:
  push_controme_temp:
    alias: "Push Snapped Temp to Controme"
    sequence:
      - service: shell_command.controme_write_virtual_sensor
        data:
          value: "{{ states('sensor.controme_temp_snapped') }}"

Schedule it:

automation:
  - alias: "Controme: Send Temp Every Minute"
    trigger:
      - platform: time_pattern
        minutes: "/1"
    action:
      - service: script.push_controme_temp

I found 1 minute strikes a good balance for Controme’s processing speed.


5) Optional read‑back verification (REST sensor)**

sensor:
  - platform: rest
    name: "Controme Virtual Temp Readback"
    resource: "http://<CONTROME_IP>/get/json/v1/<HOUSE_ID>/temps/<ROOM_ID>/?user=<USER>&password=<PASS>"
    value_template: >
      {% set s = value_json[0]['sensoren']
                 | selectattr('name','equalto','<SENSOR_ID>')
                 | list | first %}
      {{ s['wert'] if s is defined else None }}
    unit_of_measurement: "°C"
    scan_interval: 60

This lets you confirm what Controme actually stored for the target sensor ID.


Closing Thoughts & Invitation

This has been a robust way for me to feed Home Assistant room temperatures into Controme using Virtual Sensors and a lean curl call. It also reveals a bit of Controme’s internal number handling (that 16‑step decimal lattice).

If you’ve tried different interval strategies, noticed other accepted step sets, or found a cleaner HA ↔ Controme write flow (without curl), I’d love to hear it.

Happy heating—and thanks to the community for the ideas that made this possible!

1 Like