Milesight EM500-CO2: Outdoor LoRaWAN CO2 Sensor

Milesight EM500-CO2 outdoor LoRaWAN CO2 sensor: own ChirpStack/ThingsBoard decoder, decoded example, plus temperature, humidity and pressure on one device.

Milesight EM500-CO2
EM500-CO2Sensor
LoRaWAN
Class A, OTAA
Band / port
EU868 / port 85
Ingress protection
IP66
CO2 range
0 to 5000 ppm (NDIR)
Temperature / humidity
-30 to +70 °C / 0 to 100 % RH
Barometric pressure
300 to 1100 hPa
Battery
Replaceable, up to several years
Measurements

What the EM500-CO2 measures

CO2

NDIR sensor, 0 to 5000 ppm, the lead measurement for air quality and ventilation.

Temperature

-30 to +70 °C, useful for outdoor and harsh environments.

Humidity

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

Barometric pressure

300 to 1100 hPa, reported as hPa with one decimal.

Battery level

Reported periodically, with local 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 === 0x7d) {   // CO2 (ppm)
      data.co2 = readUInt16LE(bytes, i); i += 2;
    } else if (channel === 0x06 && type === 0x73) {   // pressure (hPa)
      data.pressure = readUInt16LE(bytes, i) / 10; i += 2;
    } else {
      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).

Channel format: 01 75 battery (%), 03 67 temperature (INT16 little-endian, /10), 04 68 humidity (/2), 05 7d CO2 (UINT16 little-endian, ppm), 06 73 pressure (UINT16 little-endian, /10, hPa). Implemented from the published Milesight byte specification. The device also sends history records (channel 0x20) when buffered and downlink responses; add those branches if you enable retransmission. For ThingsBoard the same channel logic goes into an uplink converter.

Uplink (hex)

0175640367EB00046864057DEE0206739427

Decoded JSON

{ "battery": 100, "temperature": 23.5, "humidity": 50, "co2": 750, "pressure": 1013.2 }
From the field

Configuration & pitfalls

NFC setup

Keys, collection and reporting interval, and CO2 thresholds are set over NFC with the Milesight ToolBox before rollout.

CO2 calibration

The NDIR sensor supports automatic baseline (ABC) and manual calibration. Disable ABC where CO2 never drops to fresh-air levels, otherwise the baseline drifts.

Channels can be disabled

Temperature, humidity, CO2 and pressure can each be switched off in config. If a channel is missing from the uplink, the decoder simply skips it.

Warm-up after power-on

The NDIR sensor needs a short warm-up before the first stable CO2 reading. Do not alarm on the very first uplinks after a battery change.

Your partner

How merkaio supports your EM500-CO2

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

Pre-staging & provisioning

We configure the EM500-CO2, 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 4-in-1 outdoor sensor: CO2 in ppm, temperature, relative humidity and barometric pressure, plus a periodic battery level. Each channel can be disabled in the configuration.
The NDIR sensor covers 0 to 5000 ppm. It supports automatic baseline calibration and manual calibration so the reading stays traceable over time.
Yes. It is built for outdoor and harsh environments with an IP66-rated enclosure and a -30 to +70 °C operating range, and it uses a replaceable high-capacity battery for long runtimes.
That is normal. The battery level is reported only periodically, so most uplinks carry just the sensor channels. The decoder skips any channel that is not present.
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.