Milesight WT102: LoRaWAN Radiator Thermostat (Smart TRV)

Milesight WT102 LoRaWAN radiator thermostat: own ChirpStack decoder framework, decoded example and target-temperature downlinks for smart offices.

Milesight WT102
WT102Sensor
LoRaWAN
Class A, OTAA
Band / port
EU868 / port 85
Mounting
M30 x 1.5 valve thread (adapters incl.)
Temperature range
-20 to +60 °C (NTC)
Target temperature
5 to 35 °C, 0.5 °C steps
Power
2x AA batteries
Configuration
NFC (Milesight ToolBox)
Measurements

What the WT102 measures

Ambient temperature

Internal NTC, -20 to +60 °C, reported with each heating-period uplink.

Current valve opening

Actual valve position 0 to 100 % from the motor.

Target temperature

The setpoint the device is regulating to, 5 to 35 °C.

Target valve opening

Setpoint for valve-opening control mode, 0 to 100 %.

Battery level

Reported in periodic uplinks, with low-battery alarm event.

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++];

    if (channel === 0x00) {            // battery (%)
      data.battery = bytes[i]; i += 1;
    } else if (channel === 0x01) {     // ambient temperature (INT16 LE, /100)
      data.temperature = readInt16LE(bytes, i) / 100; i += 2;
    } else if (channel === 0x02) {     // motor total stroke
      data.motor_total_stroke = readUInt16LE(bytes, i); i += 2;
    } else if (channel === 0x03) {     // motor position
      data.motor_position = readUInt16LE(bytes, i); i += 2;
    } else if (channel === 0x04) {     // current valve opening (%)
      data.valve_opening = bytes[i]; i += 1;
    } else if (channel === 0x06) {     // target temperature (INT16 LE, /100)
      data.target_temperature = readInt16LE(bytes, i) / 100; i += 2;
    } else if (channel === 0x07) {     // target valve opening (%)
      data.target_valve_opening = bytes[i]; i += 1;
    } else if (channel === 0x08) {     // low-battery alarm: battery (%)
      data.low_battery_alarm = true; data.battery = bytes[i]; i += 1;
    } else {
      // calibration (0x05), event/alarm and periodic-report frames
      // (0x09..0x0E, 0x60.., 0xFF..) are configuration-dependent:
      // decode per deployment, see note
      break;
    }
  }
  return { data: data };
}

function readUInt16LE(b, i) {
  return (b[i + 1] << 8) | b[i];
}
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).

Implemented from the published Milesight byte specification. Unlike the IPSO sensors, the WT102 uses a command-ID payload: each frame starts with a command byte, no separate type byte. The basic data channels are 0x00 battery (%), 0x01 ambient temperature (INT16 LE, /100), 0x04 current valve opening (%), 0x06 target temperature (INT16 LE, /100), 0x07 target valve opening (%). The periodic-report frame (0x0E) and the event/alarm frames carry a variable structure that depends on the configured control mode (automatic temperature, valve opening or integrated), so that part is a framework we build out per deployment. As a Class A device the WT102 accepts downlinks in its receive windows to set the target temperature or valve opening.

Uplink (hex)

0064016608040606f6090707

Decoded JSON

{ "battery": 100, "temperature": 21.5, "valve_opening": 6, "target_temperature": 25.5, "target_valve_opening": 7 }
From the field

Configuration & pitfalls

NFC setup

Keys, control mode, heating period and schedules are set over NFC with the Milesight ToolBox before mounting on the valve.

Motor calibration

After mounting, the device calibrates the motor stroke against the valve. Watch the calibration result event; a failed calibration means no temperature control.

Heating vs non-heating period

The reporting interval and valve behaviour differ between the configured heating season and the off-season. Plan dashboard expectations for both.

Control mode drives the payload

Automatic temperature, valve-opening and integrated control produce different periodic-report layouts, so finalise the decoder against the mode you deploy.

Your partner

How merkaio supports your WT102

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

Pre-staging & provisioning

We configure the WT102, 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 Class A device, no Milesight gateway or cloud required. You add the codec to the device profile and provision it via OTAA.
Yes, implemented from the published Milesight byte specification. The basic data channels are decoded directly; the configuration-dependent periodic-report and alarm frames are built out per deployment.
The WT102 uses a command-ID payload and the periodic report changes shape with the control mode (automatic temperature, valve opening or integrated), so the alarm and report frames are a framework we finalise against a real uplink from your deployment.
Yes. As a Class A device the WT102 accepts downlinks in its receive windows to set the target temperature or the valve opening, so a dashboard rule can push setpoints per room.
Ambient temperature from the internal NTC, the current and target valve opening, the target temperature setpoint and the battery level. Open-window and auto-away events are reported as alarms.
It runs on two AA batteries. Runtime depends on the reporting interval and how often the motor moves; the device sends a low-battery alarm before the cells are exhausted.
It is a Class A device on LoRaWAN port 85. Setpoints, schedules and control mode are configured over NFC with the Milesight ToolBox.
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.