Milesight WT101: LoRaWAN Smart Radiator Thermostat

Milesight WT101 LoRaWAN radiator thermostat: own ChirpStack/ThingsBoard decoder, decoded example, valve control and open-window detection.

Milesight WT101
WT101Sensor
LoRaWAN
Class A, OTAA/ABP
Temperature range
-20 to +60 °C, accuracy +-0.5 °C
Valve fitting
M30 x 1.5 mm, adapters for RA/RAV/RAVL/M28
Battery
2x 1.5 V Li-FeS2 AA, up to 5 years
Ingress protection
IP30 (indoor)
Heating plans
1 date period + up to 16 schedules
Configuration
NFC (Milesight ToolBox)
Measurements

What the WT101 measures

Room temperature

Built-in sensor, -20 to +60 °C, 0.1 °C resolution; drives the valve toward the target temperature.

Target temperature

Setpoint the device is regulating to, set locally, by schedule or by downlink.

Valve opening

Current stepper-motor valve position as a percentage (0 to 100 %).

Window detection

Open-window event from a rapid temperature drop; can pause heating to save energy.

Tamper & freeze status

Install/uninstall (tamper) state and freeze-protection trigger to guard against frozen pipes.

Data into your dashboard

Integration

Sensor / controller

Measures or controls in the field and sends LoRaWAN uplinks.

LoRaWAN gateway

Receives the radio packets and forwards them to the server.

ChirpStack

Network server: manages sessions and decodes the payload.

ThingsBoard / Grafana

Dashboards, alarms, rules and reports.

ChirpStack v4 · decodeUplink
function decodeUplink(input) {
  var bytes = input.bytes;
  var data = {};

  for (var i = 0; i < bytes.length; ) {
    var channel = bytes[i++];
    var type = bytes[i++];

    if (channel === 0x01 && type === 0x75) {          // battery (%)
      data.battery = bytes[i]; i += 1;
    } else if (channel === 0x03 && type === 0x67) {   // room temperature (°C)
      data.temperature = readInt16LE(bytes, i) / 10; i += 2;
    } else if (channel === 0x04 && type === 0x67) {   // target temperature (°C)
      data.target_temperature = readInt16LE(bytes, i) / 10; i += 2;
    } else if (channel === 0x05 && type === 0x92) {   // valve opening (%)
      data.valve_opening = bytes[i]; i += 1;
    } else if (channel === 0x06 && type === 0x00) {   // tamper status
      data.tamper_status = bytes[i] === 1 ? "uninstalled" : "installed"; i += 1;
    } else if (channel === 0x07 && type === 0x00) {   // open-window detection
      data.window_detection = bytes[i] === 1 ? "open" : "normal"; i += 1;
    } else if (channel === 0x09 && type === 0x90) {   // motor stroke
      data.motor_stroke = readUInt16LE(bytes, i); i += 2;
    } else if (channel === 0x0a && type === 0x00) {   // freeze protection
      data.freeze_protection = bytes[i] === 1 ? "triggered" : "normal"; i += 1;
    } else if (channel === 0x0b && type === 0x90) {   // motor current position
      data.motor_position = readUInt16LE(bytes, i); i += 2;
    } else {
      break;
    }
  }
  return { data: data };
}

function readUInt16LE(b, i) {
  return ((b[i + 1] << 8) | b[i]) & 0xffff;
}
function readInt16LE(b, i) {
  var v = readUInt16LE(b, i);
  return v > 0x7fff ? v - 0x10000 : v;
}

Implemented from the published Milesight byte specification (Communication Protocol / User Guide).

Channel format: 01 75 battery (%), 03 67 room temperature (INT16 little-endian, /10), 04 67 target temperature (/10), 05 92 valve opening (%), 06 00 tamper, 07 00 open-window, 09 90 motor stroke, 0a 00 freeze protection, 0b 90 motor position. Implemented from the published Milesight byte specification. Downlink-response and heating-schedule frames (0xf8/0xf9/0xfe/0xff) appear only after configuration and can be added when needed; for ThingsBoard the same channel logic goes into an uplink converter.

Uplink (hex)

0175640367CD000467DC0005923C070000

Decoded JSON

{ "battery": 100, "temperature": 20.5, "target_temperature": 22, "valve_opening": 60, "window_detection": "normal" }
From the field

Configuration & pitfalls

NFC setup

Keys, reporting interval, heating plans and child lock are set over NFC with the Milesight ToolBox before mounting on the radiator.

Valve calibration

After fitting, run the motor stroke calibration so the device learns the valve travel; a failed calibration is reported and the valve will not regulate correctly.

Open-window strategy

Decide whether the valve keeps its position or closes when a window-open event fires, and tune the temperature-drop threshold to avoid false triggers from drafts.

Offline control mode

Choose how the valve behaves if LoRaWAN drops: keep position, run embedded temperature control, or close. Set this explicitly so rooms do not overheat during an outage.

Your partner

How merkaio supports your WT101

From sourcing to day-to-day operation, all from one partner on our own European infrastructure.

Pre-staging & provisioning

We configure the WT101, set keys, intervals and alarms, and ship it ready to deploy.

Own decoder

Payload codec for ChirpStack v4 and ThingsBoard, implemented from the Milesight specification.

Dashboard integration

Data lands in your ThingsBoard or Grafana, with alarms and reports.

Operations & monitoring

We run the LoRaWAN stack and dashboards on European infrastructure, you just use the data.

Frequently asked questions

Yes. It is a standard LoRaWAN device, no Milesight gateway or cloud required. You add the codec to the device profile and provision it via OTAA.
Yes, for both ChirpStack and ThingsBoard, implemented from the published Milesight byte specification. The same channel logic goes into a ThingsBoard uplink converter.
It is a Class A device and supports OTAA and ABP. Each periodic uplink carries room temperature, target temperature and valve opening; battery is reported with the status frame.
Yes. As a thermostat the WT101 accepts downlinks to set the target temperature, switch temperature-control mode and push heating schedules, so you can steer it from the dashboard or by rule.
The device watches for a rapid temperature drop and reports a window-open event. You configure whether the valve holds its position or closes, which saves energy when a window is opened in winter.
It runs on two replaceable 1.5 V Li-FeS2 AA cells (3000 mAh total) for up to five years, depending on the reporting interval and how often the motor moves.
The default fitting is M30 x 1.5 mm. Adapters are available for RA, RAV, RAVL, Giacomini and M28 (Comap, Herz, TA) valve bodies, covering most common European radiators.
From the same series

Related devices

Let's discuss your infrastructure. Digital and on-site.

Whether it's IoT platform development, hardware selection, managed hosting for ChirpStack, ThingsBoard, Grafana or NetBird VPN, or migration from a self-hosted setup - we'll find the right solution for your use case. Book a free 30-minute consultation, no commitment required.

Timo Wevelsiep

Your contact

Timo Wevelsiep

Founder, merkaio

15 minutes, no commitment, directly with Timo.

By submitting, you agree to our Privacy Policy.

Decoder for ChirpStack v4. merkaio is an independent integrator and is not affiliated with Milesight.