Milesight AM103: 3-in-1 LoRaWAN Air Quality Sensor

Milesight AM103 LoRaWAN CO2, temperature & humidity sensor: own ChirpStack/ThingsBoard decoder, decoded example and smart-office integration.

Milesight AM103
AM103Sensor
LoRaWAN
Class A, OTAA
Band / port
EU868 / port 85
CO2 range
400 to 5000 ppm (NDIR)
Temperature
-20 to +60 °C
Humidity
0 to 100 % RH
Battery
Dual battery, up to 3 years (AM103) / 4 years (AM103L)
Configuration
NFC (Milesight ToolBox)
Measurements

What the AM103 measures

CO2

NDIR sensor, 400 to 5000 ppm, with optional ABC self-calibration.

Temperature

Measurement range -20 to +60 °C.

Humidity

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

Air-quality LED

Tri-colour LED and emoticon display show CO2 status at a glance.

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 === 0x07 && type === 0x7d) {   // CO2 (ppm)
      data.co2 = readUInt16LE(bytes, i); 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), 07 7d CO2 (UINT16 little-endian, ppm). Implemented from the published Milesight byte specification. The same channel logic goes into a ThingsBoard uplink converter. History uplinks (channel 20) and downlink-response frames (channel FF/FE) carry extra fields that you can add when you need them.

Uplink (hex)

0175640367E50004685C077D9001

Decoded JSON

{ "battery": 100, "temperature": 22.9, "humidity": 46, "co2": 400 }
From the field

Configuration & pitfalls

NFC setup

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

CO2 calibration

The NDIR sensor uses ABC self-calibration, which assumes the room reaches outdoor CO2 levels (around 400 ppm) regularly. In rooms that are never empty, disable ABC and run a manual calibration instead.

Warm-up after power-on

The CO2 reading needs a short warm-up after each power cycle. Treat the first uplinks after a battery change as settling values, not alarms.

Threshold alarms

CO2 threshold alarms are sent immediately, outside the reporting interval. Dashboard rules should treat alarm uplinks as priority events.

Your partner

How merkaio supports your AM103

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

Pre-staging & provisioning

We configure the AM103, 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.
Three parameters: CO2 concentration, temperature and humidity. A tri-colour LED and emoticon display also show the current air-quality status on the device itself.
It is a Class A device on LoRaWAN port 85. Each uplink carries CO2, temperature and humidity; the battery level is reported periodically.
The NDIR sensor supports automatic baseline calibration (ABC), which assumes the room reaches fresh-air levels regularly. For rooms that are continuously occupied, disable ABC and calibrate manually so readings stay accurate.
The AM103 runs up to 3 years on its dual batteries and the AM103L up to 4 years, depending on the reporting interval you configure over NFC.
Yes. CO2 thresholds are set over NFC with the Milesight ToolBox and are sent immediately, outside the regular reporting interval, so dashboard rules should treat alarm uplinks as priority events.
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.