milesight / em300-th
Milesight EM300-TH
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}`] };
}
}