Milesight WS203: LoRaWAN PIR Motion & Temperature/Humidity Sensor

Milesight WS203 LoRaWAN PIR motion plus temperature/humidity sensor: own ChirpStack/ThingsBoard decoder, decoded example and smart-office integration.

Milesight WS203
WS203Sensor
LoRaWAN
Class A, OTAA
Band / port
EU868 / port 85
PIR detection
Up to 6 m, 120° H / 100° V
Temperature
0 to +50 °C indoor range
Humidity
0 to 100 % RH
Battery
4000 mAh ER18505, up to 5 years
Configuration
NFC (Milesight ToolBox)
Measurements

What the WS203 measures

Occupancy (PIR)

Passive infrared motion, reported as occupied or vacant.

Temperature

Built-in TH sensor, indoor comfort range with high accuracy.

Humidity

Relative humidity 0 to 100 % RH (non-condensing).

Battery level

Reported periodically, with local history storage and retransmission.

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) {   // temperature (°C)
      data.temperature = readInt16LE(bytes, i) / 10; i += 2;
    } else if (channel === 0x04 && type === 0x68) {   // humidity (%RH)
      data.humidity = bytes[i] / 2; i += 1;
    } else if (channel === 0x05 && type === 0x00) {   // occupancy (PIR)
      data.occupancy = bytes[i] === 1 ? "occupied" : "vacant"; i += 1;
    } else if (channel === 0x83 && type === 0x67) {   // temperature + alarm
      data.temperature = readInt16LE(bytes, i) / 10;
      data.temperature_alarm = bytes[i + 2] === 1 ? "threshold alarm" : "release";
      i += 3;
    } else {
      break;
    }
  }
  return { data: data };
}

function readInt16LE(b, i) {
  var v = (b[i + 1] << 8) | 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 temperature (INT16 little-endian, /10), 04 68 humidity (/2), 05 00 occupancy (1 occupied, 0 vacant), 83 67 temperature with a trailing alarm flag. Device-info and history channels (0xFF, 0x20 0xCE) carry firmware metadata and buffered records; add them if you parse stored history. For ThingsBoard the same channel logic goes into an uplink converter. Implemented from the published Milesight byte specification.

Uplink (hex)

0175630367E5000468640500

Decoded JSON

{ "battery": 99, "temperature": 22.9, "humidity": 50, "occupancy": "vacant" }
From the field

Configuration & pitfalls

NFC setup

Keys, reporting interval and PIR sensitivity are set over NFC with the Milesight ToolBox before rollout.

PIR cover & range

The detection pattern depends on the fitted PIR cover; pick the cover for the room size so motion is neither missed nor over-triggered.

Occupancy debounce

PIR reports a vacant state only after a hold-off window, so dashboards should treat short gaps as still occupied to avoid flapping.

TH venting lag

After a large temperature change the built-in sensor needs time to settle on the true value; account for this when alerting on fast transitions.

Your partner

How merkaio supports your WS203

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

Pre-staging & provisioning

We configure the WS203, 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.
A passive infrared sensor reports occupancy on channel 05 00 as occupied (1) or vacant (0). Motion events and the temperature/humidity readings share the same uplink.
It is a Class A device on LoRaWAN port 85. Each uplink can carry occupancy, temperature and humidity; the battery level is reported periodically.
It ships with a 4000 mAh ER18505 Li-SOCl2 battery rated for up to five years, depending on the reporting interval and PIR activity you configure.
Yes. It stores readings locally with timestamps and retransmits them once the connection is restored, so you do not lose history during a gateway outage.
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.