LoRaWAN
The LoRaWAN page manages LoRaWAN gateways and sensor devices for long-range, low-power wireless communication with IoT sensors such as temperature probes, door contacts, water-leak detectors, and environmental monitors. GEM acts as the network server itself: a radio concentrator (an SX1302/SX1303 board) hears the sensors, a packet forwarder relays the frames to GEM over UDP, and GEM decrypts each frame and runs your payload decoder.
Open LoRaWAN
LoRaWAN is a premium integration. Adding a lorawan_gateway device — and using this page — requires the LoRaWAN product in your license. Core drivers are always included, and existing devices keep running if a license later changes. See License.
Prerequisites
- An SX1302 / SX1303 concentrator wired to the GEM server — either a USB corecell (enumerates as a serial port, typically
/dev/ttyACM0) or an SPI board (SPI bus + a reset GPIO pin). - A packet forwarder posting frames to GEM over UDP. GEM can compile and supervise the forwarder for you (managed mode), or you can run your own forwarder pointed at GEM's UDP port (external mode).
- The activation keys for each sensor, from its label or provisioning sheet:
- OTAA sensors: DevEUI, AppKey, and (if used) JoinEUI/AppEUI.
- ABP sensors: DevAddr, NwkSKey, and AppSKey.
Tabs
The page has three tabs: Gateways, Devices, and Traffic.
Gateways Tab
The Gateways tab lets you create and manage LoRaWAN gateway devices. A gateway receives radio transmissions from your LoRa sensors and forwards them to GEM.
At the top of the tab, each gateway also appears as a status card showing its connection state (Connected / Disconnected), the number of radios reporting, the uplink count in the last hour and last 24 hours, and a "fwd running" indicator when GEM is managing the packet forwarder process. The connection state updates live — the card and the table's Status badge flip to Connected or Disconnected as the gateway comes online or drops, with no page refresh needed.
Gateway Table
The table lists all configured gateways with the following columns:
| Column | Description |
|---|---|
| Name | The gateway name. |
| UDP Port | The UDP port the gateway uses for the packet forwarder protocol (default: 1700). |
| Forwarder | Shows "Managed" if a binary path is configured (GEM compiles, spawns, and supervises the packet forwarder), or "External" if left empty (you run the forwarder separately). |
| Status | Connection status badge: Connected (green) or Disconnected (red). |
Each row has these action buttons:
| Button | Description |
|---|---|
| Edit | Opens the gateway form pre-filled with this gateway's settings. |
| Reload | Restarts the gateway device driver. |
| Delete | Removes the gateway and all of its sensor zones (with confirmation). |
Click New Gateway to add a new gateway.
Gateway Form
The gateway form has the following fields:
| Field | Description |
|---|---|
| Name | Required. The gateway name (used as the device name in GEM). |
| UDP Port | The UDP port for the packet forwarder protocol. Default: 1700. |
Packet Forwarder Section
| Field | Description |
|---|---|
| Binary Path | Path to the lora_pkt_fwd binary on the GEM server. Leave empty if you run the packet forwarder externally. |
| Compile / Recompile | Clones and compiles the sx1302_hal packet forwarder from source, pinned to release V2.1.0 (supports both SX1302 and SX1303 concentrators — including RAK2287/RAK7271 and RAK5146/RAK7371 USB gateways). This may take several minutes. Recompile refreshes the cached source to the pinned release first; if the site has no GitHub access, it compiles the cached source as-is. On success, the binary path and gateway EUI are populated automatically. The button reads Compile when no path is set and Recompile once one is. |
| Gateway EUI | 16 hex character unique gateway identifier (e.g., AA555A0000000000). Auto-detected from the attached concentrator whenever possible: GEM probes it automatically when you open the New Gateway form, during compilation, and via the Detect button next to this field. Detection requires a compiled packet forwarder (the chip_id helper it installs) and the concentrator wired to the server; if neither is present the field stays blank for manual entry, which is normal for external-forwarder setups. The field is only auto-filled while empty, so anything you type is never overwritten. |
The following fields appear only when a Binary Path is configured (managed mode):
| Field | Description |
|---|---|
| Com Type | Connection type to the LoRa concentrator: USB or SPI. Changing this updates the Com Path default. |
| Com Path | Device path for the concentrator. Default: /dev/ttyACM0 for USB, /dev/spidev0.0 for SPI. When Com Type is USB, the gateway driver promotes this to a stable /dev/serial/by-id/... symlink at start-up so the dongle survives replug/reboot reordering. Set the usb_auto_discover device attribute to false (in the Attributes editor) to disable that promotion — recommended only on hosts running multiple identical concentrators. The stored by-id path is resolved back to its short /dev/tty* node each time the packet forwarder starts — the sx1302_hal binaries have a fixed-size path buffer and abort on the long by-id path, so the config file and chip_id probes always receive the short path. |
| Frequency Plan | Regional frequency plan: US915, EU868, AU915, AS923, or IN865. Must match the sensors and your local regulations. |
| Reset GPIO | GPIO pin number for the SPI concentrator reset line. Only shown when Com Type is SPI. |
Radio Section
| Field | Description |
|---|---|
| TX Power (dBm) | Transmit power requested for downlinks and join accepts, 12–27 dBm. Default: 14. At 17 or below, the external power-amplifier entries are also stripped from the generated TX gain table, so no request can engage the PA at all. Applies to managed and external forwarders (the power request rides in each downlink packet). |
| Sub-band | US915/AU915 only. The block of 8 uplink channels (1–8) the gateway listens on — it must match the sensors' channel plan. Most vendors ship sub-band 2 (channels 8–15, the default). The choice is also advertised to OTAA devices in the join accept, so joined sensors always transmit on the channels the gateway hears. |
| Antenna Gain (dBi) | Managed forwarder only. Subtracted from each requested TX power by the packet forwarder so the radiated power (EIRP) stays within regulatory limits when using a high-gain antenna. |
A USB-powered concentrator on a weak port, unpowered hub, or long/thin cable can brown out and re-enumerate during transmit bursts — the current spike from the radio PA rides on top of the corecell's steady draw. Set TX Power to 12–14 dBm (which also disables the PA) and prefer a short cable or powered hub. If the gateway resets even with no downlink traffic, the baseline draw is the problem and only the cabling/power fix will help.
Heartbeat Alerts Section
| Field | Description |
|---|---|
| Alert Email | Email address notified when any of this gateway's sensors misses its heartbeat interval. Leave empty to disable email alerts. |
| Alert SMS | Phone number for missed-heartbeat SMS alerts. Leave empty to disable SMS alerts. |
Click Save to create or update the gateway. The gateway is automatically reloaded on save, so a managed packet forwarder restarts with the new radio settings (TX power, sub-band, antenna gain). Click Cancel to close the form.
Devices Tab
The Devices tab manages LoRa sensor nodes. Each sensor is represented as a GEM zone belonging to a gateway.
Gateway Selector and Grouping
Select a gateway from the Gateway dropdown to view and manage its sensors. Use the Group By dropdown to list sensors flat (None) or grouped by subsystem.
When a gateway is selected, a row of summary cards shows the sensor counts: Total Sensors, Online, Offline, Low Battery, and Weak Signal. Sensors that have never sent an uplink (Status "No data") are counted as neither online nor offline — the Offline card shows them as a "N never reported" note so the numbers visibly add up to the total.
Sensor Table
The table lists all sensor zones for the selected gateway:
| Column | Description |
|---|---|
| Label | The sensor display name. |
| DevAddr | The device address (shown in monospace). For OTAA sensors this is the current session DevAddr (rotates on every Join); for ABP sensors it is the static DevAddr programmed into the sensor. |
| Mode | Activation mode: OTAA (green badge once joined, gray when not yet joined) or ABP. |
| Status | Online (green), Offline (red), or No data (gray). A sensor is considered offline if no uplink has been received within its offline window (default: 24 hours — see Offline detection and alerts). |
| Battery | Battery level if reported by the sensor — percentage or voltage, color-coded good/low/critical. When enough history exists, a ~Nd badge estimates the days of battery remaining. |
| Last Uplink | Time since the last received packet (e.g., "5m ago", "2h ago"). Hover to see the full timestamp. |
| RSSI | Signal strength of the last received packet. |
Click any sensor row to expand it. The expanded panel shows packet statistics for the last period — Packets/hr, Avg RSSI, Avg SNR, FCnt Gaps (missed frames), and Total Packets — a small activity sparkline, and the most recent Decoded Values the payload decoder produced.
The expanded panel also holds a Reset Frame Counters button, and shows a warning when recent uplinks have been rejected as frame-counter replays. Replay protection rejects any frame whose counter is equal to or lower than the last accepted one, so a sensor that was rebooted, rekeyed, or factory reset restarts at zero and looks dead while every uplink is discarded. Resetting clears the stored uplink/downlink counters (and, for OTAA sensors, the recorded DevNonces) so the device is accepted again.
Each row has these action buttons:
| Button | Description |
|---|---|
| Edit | Opens the sensor form pre-filled with this sensor's settings. |
| Downlink | Opens the downlink form to send a command back to this sensor (see Sending Downlinks). |
| Duplicate | Opens a new sensor form pre-filled with the same subsystem, payload decoder, and heartbeat interval — it clears the name and label and generates a fresh set of random ABP keys. |
| Delete | Removes the sensor zone (with confirmation). |
Below the table, the action bar has these buttons:
| Button | Description |
|---|---|
| New Sensor | Opens the sensor form to add a sensor. |
| Profiles | Opens the Device Profiles panel for reusable decoder/heartbeat/downlink presets. |
| Discovered | Opens the Discovered Devices panel, which lists sensors heard in the traffic log that don't yet have a zone. |
| Import | Bulk-imports sensors from a .json or .csv file — see Bulk Import for the expected fields and format. |
| Export | Downloads every sensor on the selected gateway as a JSON file in the same format Import accepts — see Export. |
Sensor Form
| Field | Description |
|---|---|
| Name | Required. Lowercase zone name, no spaces (e.g., temp_sensor_1). |
| Label | Display name (e.g., Temperature Sensor 1). Auto-filled from the name when left blank (temp_sensor_1 → Temp Sensor 1). |
| Subsystem | Required. The GEM subsystem this sensor belongs to (e.g., sensors, climate, security). |
| Profile | Optional. Appears when at least one device profile exists. Pick a profile and click Apply to fill in the decoder, heartbeat interval, and downlink templates from that profile. |
Activation
Choose the activation mode from the dropdown next to the Activation heading. It matches how the physical sensor is configured:
- ABP (Activation By Personalization) — session keys and DevAddr are pre-programmed on the sensor and entered into GEM.
- OTAA (Over-The-Air Activation) — the sensor joins the network by exchanging keys with GEM. DevAddr and session keys are derived on each Join and rotate automatically. New sensors default to OTAA.
The Generate button (next to the mode dropdown) fills in random keys for the currently selected mode: for ABP it generates DevAddr, NwkSKey, and AppSKey; for OTAA it generates DevEUI and AppKey. Use it when you are provisioning a sensor you can program yourself rather than entering keys from a label.
In OTAA mode, a Scan Label button lets you use the device camera to read a QR code or label and auto-fill the OTAA identifiers. If you already have a photo or screenshot of the label, use the Upload Image button to pick the file, or simply paste an image from the clipboard (Ctrl+V) while the sensor form is open — both feed the same scanner and auto-fill DevEUI, AppEUI/JoinEUI, and AppKey. The scanner reads the label with the AI assistant's Anthropic provider, so an Anthropic API key must be configured under Admin → AI Assistant (or in gem.json). The label is read twice and the passes are compared — if a field differs between reads, a warning asks you to verify that value against the physical label before saving.
ABP Fields
| Field | Description |
|---|---|
| DevAddr | Required. 4-byte (8 character) hex device address. |
| NwkSKey | Required. 16-byte (32 character) hex network session key. |
| AppSKey | Required. 16-byte (32 character) hex application session key. |
OTAA Fields
| Field | Description |
|---|---|
| DevEUI | Required. 8-byte (16 character) hex unique device identifier. Static — programmed into the sensor at manufacture. Checked for duplicates on blur and again at save — a DevEUI (or ABP DevAddr) already provisioned as a sensor on any gateway shows "already provisioned on <gateway> as <sensor>" and blocks saving. When editing, the sensor's own address is exempt. |
| AppKey | Required. 16-byte (32 character) hex application key used to derive session keys during Join. |
| JoinEUI | Optional. 8-byte hex join server identifier. Defaults to zeros if omitted. |
When editing an OTAA sensor, the form shows its join state — a Joined badge with the current DevAddr and join time, or Not joined.
For OTAA sensors, the DevEUI is the static identifier used to match incoming Join requests. After a successful Join, GEM derives the current DevAddr, NwkSKey, and AppSKey and stores them as zone attributes. The DevAddr column in the sensor table reflects the current session DevAddr; dev_addr is a read-only attribute that rotates on every re-join. The NwkSKey and AppSKey fields are not shown in the OTAA form — they are populated automatically.
The DevEUI, AppKey, and JoinEUI fields (and the ABP DevAddr/NwkSKey/AppSKey fields) validate live as you type: a red border and message flag a wrong length or non-hex characters, and separators (-, :, spaces) are stripped automatically when pasting values copied from a label or vendor portal. Save stays disabled while any field is invalid.
When you edit an OTAA sensor that has not joined yet, a diagnosis line appears under the "Not joined" badge explaining what the gateway has actually seen from that DevEUI — no join request at all (check power/range/DevEUI), a join request whose MIC failed (the AppKey doesn't match — re-check or re-scan the label), a DevNonce replay (factory-reset device — use Reset Frame Counters), or an accept the device never confirmed (missed RX window). It also counts join attempts and MIC failures over the last 24 hours.
Monitoring
| Field | Description |
|---|---|
| Heartbeat Interval (seconds) | The cadence at which this sensor is expected to send uplinks. Default: 43200 (12 hours). A dropdown beside the field offers common intervals (15 minutes through 7 days) and fills the value in; any custom number of seconds can still be typed. Missed heartbeats trigger email/SMS alerts when those are configured on the gateway form (see Offline detection and alerts). |
| Device Class | A (default) or C. Class A devices only listen briefly after their own uplinks, so downlinks queue until the next uplink; Class C devices listen continuously and receive downlinks immediately. Must match how the physical sensor is configured — see Device class and RX timing. |
When editing an existing sensor, an Alarm Presets row offers one-click buttons — Water Leak, Door Open, Temp High, Temp Low, Battery Low — that each create a matching attribute trigger on the sensor (e.g., "Battery Low" fires when battery_percent drops below 20).
Downlink Command Mapping
The Downlink Command Mapping section maps standard GEM zone commands (on, off, open, close, stop, toggle) to downlink payloads, so a LoRa actuator — a valve, relay, or siren — can be controlled from macros, widgets, schedules, and voice like any other zone. Click Add Mapping, pick a verb, and enter the hex payload and fPort (or fill them from a profile's downlink template). Each mapping is stored as a <verb>_action override on the zone; when the command fires, GEM dispatches the mapped downlink through the gateway, resolving the sensor's current DevAddr at send time (so OTAA re-joins never break a mapping). Class C devices receive the command immediately; Class A devices on their next uplink. Removing a mapping row and saving clears the override.
Payload Decoder Section
| Field | Description |
|---|---|
| Template | Select a pre-built decoder template from the dropdown to populate the decoder text area. Templates cover generic shapes (Temperature + Humidity, Door/Window Contact, Water Leak, raw hex dump), the Cayenne LPP and Elsys generic TLV formats (each of which covers a whole family of devices), and specific sensor models: Dragino LHT65 / LDS02 / LWL02 / LDDS75 / LSE01, Milesight EM300-TH / EM310-UDL / AM103 / WS301 / WS101 / WS202, Sensative Strips (Drip / Comfort / Guard), Browan TBWL100 / TBMS100, and Netvox R311A. |
| Decoder | JavaScript function body that decodes the raw payload bytes into attribute values. Receives bytes (Buffer) and port (fPort). Must return an object of attribute name/value pairs. |
Example decoder:
// Decode a temperature sensor payload
return { temperature: bytes.readInt16BE(0) / 100 };
Two helpers sit alongside the decoder:
- Auto-detect (shown when editing a sensor that has no decoder yet) tests the built-in templates against the sensor's recent real payloads and lists the templates that decode cleanly, ranked by success rate — click Apply to use one.
- Test lets you paste a hex payload and an fPort and run the decoder immediately, showing the decoded object or the error so you can iterate before saving.
Click Save to create or update the sensor. The gateway device is automatically reloaded so it picks up the new or changed zone. Click Cancel to close the form.
Discovered Devices
Click Discovered to scan the gateway's recent traffic log for sensors that are transmitting but don't yet have a zone. Each unknown device is listed by its DevAddr/EUI with the packet count, last-seen time, and RSSI. Click Add to open a pre-filled sensor form for that device. Click Close to dismiss the panel.
On sites with more than one gateway, a device that is already provisioned on a different gateway shows an "on <gateway>" badge instead of an Add button — it is being heard here through overlapping radio coverage, and adding it again would create a duplicate. To move a sensor between gateways, delete it from the old gateway first.
Bulk Import
Click Import to add many sensors at once from a .json or .csv file. The imported sensors are attached to the gateway currently selected in the Gateway dropdown (the file does not specify a gateway), and each is created enabled.
Rows whose DevEUI or DevAddr is already provisioned — on any gateway, or earlier in the same file — are skipped and reported in the import results ("already provisioned on <gateway> as <sensor>"), so re-importing an export never creates duplicates.
The file type is chosen by its extension:
- JSON — an array of sensor objects (a single bare object is also accepted). Use JSON whenever a value contains a comma — most importantly a
payload_decoder, since decoder code almost always does. - CSV — the first line is a header row of field names; each following line is one sensor, with comma-separated values in the same column order. The CSV reader is deliberately simple: it splits on commas with no quoting or escaping, so any value that itself contains a comma will break the row. Don't import decoders via CSV — use JSON for those.
Each sensor entry recognizes the following fields. Only name is effectively required; every other field is optional and is skipped when empty, so a file can mix OTAA and ABP sensors and partial rows.
| Field | Description |
|---|---|
name | Lowercase zone name, no spaces (e.g., temp_sensor_1). Also used to label the row in any import error. |
label | Display name. Defaults to name if omitted. |
subsystem_id | Numeric id of the GEM subsystem the sensor belongs to. Defaults to 0. |
activation_mode | OTAA or ABP. |
dev_eui | OTAA only. 16-character DevEUI — the identifier the Join request is matched against. |
app_key | OTAA only. 32-character AppKey. |
join_eui | OTAA only, optional. 16-character JoinEUI/AppEUI. Defaults to zeros if omitted; not required for joining (matching is by DevEUI + AppKey). |
dev_addr | ABP only. DevAddr. Leave blank for OTAA sensors — their DevAddr is assigned at Join and rotates. |
nwk_s_key | ABP only. NwkSKey. |
app_s_key | ABP only. AppSKey. |
payload_decoder | JavaScript decoder source for this sensor. JSON files only (contains commas). |
heartbeat_interval | Expected uplink interval in seconds, used for offline detection. |
device_class | A or C — see Device class and RX timing. |
Any other columns or keys are ignored. After the import, GEM reloads the gateway and a toast reports how many sensors were imported and how many failed.
JSON example:
[
{
"name": "soil_probe_01", "label": "Soil Probe 01", "subsystem_id": 11,
"activation_mode": "OTAA",
"dev_eui": "0011223344556677",
"app_key": "00112233445566778899AABBCCDDEEFF",
"heartbeat_interval": 7200,
"payload_decoder": "function decode(bytes){ return { temp: bytes[0] }; }"
},
{
"name": "door_contact_02", "label": "Door Contact 02", "subsystem_id": 11,
"activation_mode": "ABP",
"dev_addr": "26011F88",
"nwk_s_key": "0A1B2C3D4E5F60718293A4B5C6D7E8F9",
"app_s_key": "F9E8D7C6B5A4938271605F4E3D2C1B0A"
}
]
CSV example:
name,label,subsystem_id,activation_mode,dev_eui,app_key,heartbeat_interval
soil_probe_01,Soil Probe 01,11,OTAA,0011223344556677,00112233445566778899AABBCCDDEEFF,7200
Export
Click Export to download every sensor on the selected gateway as a JSON file. The file uses exactly the field names Bulk Import accepts — including activation_mode, activation keys, payload_decoder, heartbeat_interval, and device_class — so it round-trips: export from one gateway (or before a rebuild), import on another, and the fleet is reprovisioned. This matters especially for ABP sensors, whose session keys cannot be recovered from the hardware.
The exported file contains the sensors' secret keys (AppKey, NwkSKey, AppSKey). Treat it like a credential file — store it encrypted and don't commit it anywhere.
Device Profiles
Click Profiles to manage reusable sensor presets. A profile bundles a payload decoder, a heartbeat interval, and a set of downlink templates so you can apply consistent settings across many identical sensors. Create a profile by giving it a name, pasting decoder code, setting the heartbeat, and adding any number of named downlink templates (name + hex payload + fPort). Existing profiles can be edited or deleted from the table. Apply a profile to a sensor with the Profile picker in the sensor form.
Sending Downlinks
Click Downlink on a sensor row to open the downlink form for that sensor:
| Field | Description |
|---|---|
| Payload (hex) | The downlink bytes as a hex string (e.g., 0102FF). |
| FPort | The downlink port (1–223). |
| Template | Optional. Appears when downlink templates are available (from the device's profile). Selecting one fills in the payload and fPort. |
| Confirmed | When checked, requests an acknowledgement from the sensor. |
| Queue (Class A) | When checked, the downlink is explicitly queued for the sensor's next uplink rather than attempting an immediate send. |
Queued downlinks are listed under Pending Queue with a Cancel option. The button reads Queue Downlink when Queue is checked and Send Downlink otherwise.
How a downlink reaches the sensor depends on its device class
LoRaWAN sensors only listen for downlinks at specific times, so GEM schedules each frame into the right receive window based on the sensor's Device Class attribute (see Device class and RX timing):
- Class A (default) — the sensor only opens a brief receive window right after it sends an uplink. GEM therefore queues the downlink and transmits it in the RX1 window of the next uplink, through the same gateway that heard that uplink. This happens whether or not you check Queue — sending to a Class A sensor with no uplink pending simply queues the frame. The confirmation message reads "downlink queued — sends in RX1 on the next uplink." For a battery sensor that uplinks every few hours, expect a corresponding delay before the command lands.
- Class C — the sensor listens continuously on the RX2 channel, so GEM transmits the downlink immediately on the region's RX2 frequency. The confirmation message reads "downlink sent (RX2)."
Only one queued frame is delivered per uplink, and a queued frame is kept (not dropped) if the transmit fails — it retries on the following uplink.
Device class and RX timing
The Device Class is set directly on the sensor form (Monitoring section): A (default) queues downlinks for the next uplink's RX1 window; C receives immediately on RX2. It must match how the physical sensor is configured.
One further advanced attribute can be set per sensor in the Attributes editor:
| Attribute | Description |
|---|---|
rx_delay | RX1 delay in seconds — the gap between a Class A uplink and its RX1 receive window. Must match the device's provisioned RX_DELAY (1 for most devices, and what OTAA joins are told). |
Traffic Tab
The Traffic tab shows a live log of LoRa packets for a gateway.
Gateway Selector
Select a gateway to monitor. Packets appear in real time as they arrive — the tab subscribes to the gateway's live feed, so there is no fixed refresh interval. Click Refresh to reload the full stored log on demand.
Filters and Export
A filter bar lets you narrow the log:
- Device — All Devices, or a specific sensor.
- Direction — All, Uplink, Downlink, or Join.
- MIC — All, MIC OK, or MIC Fail.
- Time — All Time, Last 1 hour, Last 24 hours, or Last 7 days.
A packet count above the table shows how many packets match (and how many were filtered out). CSV and JSON buttons export the filtered log.
Channel Utilization
When uplinks have arrived in the last hour, a Channel Utilization table appears above the traffic log with one row per radio channel: the packet count, its share of all uplinks, the average RSSI, the estimated on-air time, and that airtime as a duty-cycle percentage of the hour. Airtime is estimated from each packet's spreading factor, bandwidth, and payload size. Use it to spot channels a noisy device is saturating, confirm sensors are hopping channels as expected, and — on EU868 sites — to keep an eye on the regulatory duty-cycle limits (0.1%–10% per sub-band depending on the band).
Traffic Table
| Column | Description |
|---|---|
| Time | The time the packet was received. |
| Dir | Direction arrow: ↑ uplink, ↓ downlink, J↑ join request, J↓ join accept. |
| DevAddr | The device address (or DevEUI for join requests) of the sending sensor, shown in monospace. For OTAA sensors this is the current session DevAddr assigned at Join. |
| Zone | The GEM zone name matched to this device address, or "<unknown>" if no matching zone exists. |
| RSSI | Received signal strength indicator. |
| SNR | Signal-to-noise ratio. |
| Freq | The radio frequency used. |
| Data Rate | The LoRa data rate (spreading factor and bandwidth). |
| FCnt | The frame counter value. A -N badge flags a gap of N missing frames since the previous packet. |
| MIC | Message Integrity Code verification: OK (green badge) or FAIL (red badge). A Replay badge appears when a frame is rejected for an equal-or-lower frame counter. |
| Info | Context for the row: decoded payload values for an uplink; fPort + payload and the ACK state (Awaiting ACK / ACK'd) for a downlink; the assigned DevAddr for a join accept. |
Click any packet row to expand it. The detail row shows which other gateways also heard the frame (with their per-gateway RSSI/SNR) and the full raw packet as JSON — useful when diagnosing multi-gateway coverage or a decoder problem.
When GEM is managing the packet forwarder, a Packet Forwarder Log section appears below the table with the forwarder's own stdout/stderr, plus Copy and Clear buttons.
Use the Traffic tab to verify that sensors are communicating correctly. If you see packets with MIC FAIL, the NwkSKey or AppSKey on the sensor does not match what is configured in GEM. A Replay badge instead means the sensor's frame counter went backwards — typically after a reboot, rekey, or factory reset. Expand the sensor's row on the Devices tab and click Reset Frame Counters so new uplinks are accepted.
Offline detection and alerts
Two separate settings govern how a quiet sensor is treated:
- Status badge (
offline_threshold) — the Devices tab marks a sensor Offline when no uplink has arrived within its offline window. The default is 24 hours. To change it per sensor, set theoffline_thresholdzone attribute (in seconds) in the Attributes editor. - Missed-heartbeat alerts (
heartbeat_interval) — the Heartbeat Interval field on the sensor form (default 43200 = 12 hours) is the expected uplink cadence. When a sensor goes silent past this interval, the gateway sends an email and/or SMS alert — provided the Alert Email and/or Alert SMS fields are set in the gateway form's Heartbeat Alerts section.
Related Documentation
- Devices — Gateway device configuration
- Zones — Sensor zone management
- Attributes — Setting
offline_thresholdandusb_auto_discover - Triggers — Alarms on sensor values