milesight / em300-th

Milesight EM300-TH

Datasheet Vendor Last verified: 2026-05-27

Milesight devices often use TLV (type-length-value) structures. FPort and channel mask depend on configuration — adjust the sample to match your deployment.

Decoder

Copy into ChirpStack or paste in the playground.

// Milesight EM300-TH — temperature & humidity (Milesight TLV-style example; verify port & version)

function readInt16BE(buf, offset) {
  const v = (buf[offset] << 8) | buf[offset + 1];
  return v & 0x8000 ? v - 0x10000 : v;
}

function decodeUplink(input) {
  try {
    const bytes = input.bytes;
    const decoded = {};
    let i = 0;
    while (i + 2 < bytes.length) {
      const cid = bytes[i];
      const len = bytes[i + 1];
      i += 2;
      const end = i + len;
      if (end > bytes.length) break;
      const slice = bytes.subarray(i, end);
      if (cid === 0x01 && len >= 2) {
        decoded.temperature_c = readInt16BE(slice, 0) / 10;
      }
      if (cid === 0x02 && len >= 2) {
        decoded.relative_humidity = (((slice[0] << 8) | slice[1]) / 10).toFixed(1);
      }
      if (cid === 0x05 && len >= 1) {
        decoded.battery_percent = slice[0];
      }
      i = end;
    }
    return { data: decoded };
  } catch (err) {
    return { errors: [`Decoder error: ${err.message}`] };
  }
}

← Codec library