Milesight GS601: LoRaWAN Vape & Smoke Detector
Milesight GS601 LoRaWAN vape & smoke detector: own ChirpStack/ThingsBoard decoder, decoded example, vaping-index alarms and smart-school integration.
- LoRaWAN
- Class C, OTAA
- Band / port
- EU868 / port 85
- Detection area
- 4 x 4 m, mount at 2.4 to 3 m
- Sensors
- TVOC, PM1.0/2.5/10, temperature, humidity
- Privacy
- No camera, no microphone
- Local alerts
- Buzzer + LED, tamper detection
- Power
- USB-C / mains powered
What the GS601 measures
Vaping index
Composite 0 to 100 score (UINT8) that rises during a vaping or smoking event; the primary alarm value.
TVOC
Total volatile organic compounds in ppb (UINT16 LE), the main air-chemistry signal behind the vaping index.
Particulate matter
PM1.0, PM2.5 and PM10 in micrograms per cubic metre (each UINT16 LE).
Temperature & humidity
Onboard climate readings (temperature INT16 LE /10 in degrees C, humidity UINT16 LE /10 in % RH) for context and burning alarms.
Tamper & occupancy
Tamper-trigger flag (UINT8) plus optional occupancy status (0 vacant / 1 occupied).
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.
function decodeUplink(input) {
var bytes = input.bytes;
var data = {};
for (var i = 0; i < bytes.length; ) {
var id = bytes[i++];
if (id === 0x00) { // battery (%)
data.battery = bytes[i]; i += 1;
} else if (id === 0x01) { // vaping index (0..100)
data.vaping_index = bytes[i]; i += 1;
} else if (id === 0x03) { // PM1.0 (ug/m3)
data.pm1_0 = readUInt16LE(bytes, i); i += 2;
} else if (id === 0x05) { // PM2.5 (ug/m3)
data.pm2_5 = readUInt16LE(bytes, i); i += 2;
} else if (id === 0x07) { // PM10 (ug/m3)
data.pm10 = readUInt16LE(bytes, i); i += 2;
} else if (id === 0x09) { // temperature (C)
data.temperature = readInt16LE(bytes, i) / 10; i += 2;
} else if (id === 0x0b) { // humidity (%RH)
data.humidity = readUInt16LE(bytes, i) / 10; i += 2;
} else if (id === 0x0d) { // TVOC
data.tvoc = readUInt16LE(bytes, i); i += 2;
} else if (id === 0x0f) { // tamper status (0/1)
data.tamper = bytes[i]; i += 1;
} else if (id === 0x12) { // occupancy (0/1)
data.occupancy = bytes[i]; i += 1;
} else {
break; // alarm frames, raw TVOC blocks and config replies are deployment-specific
}
}
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).
Command-id format: 00 battery (%), 01 vaping index, 03/05/07 PM1.0/PM2.5/PM10 (UINT16 LE), 09 temperature (INT16 LE, /10), 0b humidity (UINT16 LE, /10), 0d TVOC, 0f tamper, 12 occupancy. This is the periodic-report path, implemented from the published Milesight byte specification. Alarm frames (e.g. command id 02 for a vaping-index alarm) and raw TVOC blocks carry extra type bytes and are deployment-specific, so the loop breaks on unknown ids; we extend it for the alarm types you actually use. The same logic goes into a ThingsBoard uplink converter.
Uplink (hex)
00640114030500050800070C0009E1000BE0010D9600Decoded JSON
{ "battery": 100, "vaping_index": 20, "pm1_0": 5, "pm2_5": 8, "pm10": 12, "temperature": 22.5, "humidity": 48, "tvoc": 150 }Configuration & pitfalls
Class C power
The GS601 is a Class C device with continuous receive, so it runs on USB-C or mains, not on battery. Plan a power outlet at the mounting point.
Placement
Detection area is about 4 x 4 m at a mounting height of 2.4 to 3 m. Centre it over the monitored space and keep it clear of vents that flush the air.
Privacy by design
No camera and no microphone: it senses air chemistry only. This is the key selling point for restrooms and changing rooms, document it for stakeholders.
Alarm vs report frames
Periodic reports and event alarms use different command ids. Treat vaping-index alarm uplinks as priority events and decode the alarm type explicitly when you enable them.
How merkaio supports your GS601
From sourcing to day-to-day operation, all from one partner on our own European infrastructure.
Pre-staging & provisioning
We configure the GS601, 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
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.
Your contact
Timo Wevelsiep
Founder, merkaio
15 minutes, no commitment, directly with Timo.
Decoder for ChirpStack v4. merkaio is an independent integrator and is not affiliated with Milesight.