Skip to main content

Dragino LDS02

LoRaWAN Door Sensor Mk.2

Introduction

The Dragino LDS02 is a self-contained sensor with LoRaWAN, 2xAAA batteries, a magnetic reed proximity switch and accompanying magnet. When the magnet is aligned to the sensor and closer than a centimeter, the switch is closed. When the magnet is moved further, the switch is open.

Resources

Product Page

Datasheet

Manual

Add Device to Console

To start, you'll need to add your device to the Helium Console. In the package is a sticker containing the Device EUI (also QR code), App EUI, and App Key. (The APSSKEY and NETSKEY are unused.) Follow our quick start for instructions to add a new device to Console.

Open the Debug panel on the Device view to observe incoming messages for the next step.

Install Batteries

Open the LDS02 enclosure and add two AAA battery cells for power. For the best wide-range temperature tolerance and longevity, consider Lithium primary cells, such as Energizer Ultimate Lithium L92SBP.

On insertion, the LED should light quickly Red, Blue, Green, then off. You should immediately see Join and Uplink messages on the Helium Console Debug panel. If you see no messages, or no LED flashing, double-check the device IDs, then remove and reinstall one battery to start initialization again.

myDevices Cayenne

This device is supported directly by myDevices Cayenne via the included Integration in Helium's Console.

To add the LDS02 to Cayenne, you do not need to set up a Decode script at all. Cayenne takes the encoded Device payload directly and parses the events from it.

Be careful to select Helium when adding the LDS02 to Cayenne. As described here, select

  1. "Add new..."
  2. "Device/Widget"
  3. "LoRa"
  4. "Helium"
  5. select Dragino LDS02 LoRaWAN Door Sensor
  6. Enter the Device EUI and other information.

On the Helium Console, select Flow and directly connect the LHT65 Device to the Cayenne Integration with a connecting flow line. Do not use a Decoder.

Cayenne will show:

  • RSSI (dBm)
  • SNR (dB)
  • Battery Voltage (v)
  • Battery (%)
  • Door state (0/1)
  • Door ("Dorr" sic) Open Times
  • Last Door Open Duration (in minutes!)
  • Alarm state (0/1)

Decode Device Payload

To decompose the packed 10-byte data Payload from the device into individual values, you may provide a decode Function as explained in our short primer. The manufacture of this device, Dragino, is using their own encoding scheme to define which bytes hold which piece of data. Below is a table taken from the manual showing the size and location of each piece of data.

If you would like to decode the device payload to view it in Console or send to your own application, this section will show you how. We'll be using a Console Function Decoder to unpack the device payload into a human readable form.

Create Function Decoder

Create a new custom Function decoder, by selecting Functions, then (+). Name the function (perhaps "LDS02"), type Decoder and Custom Script. Paste the script below, provided by Dragino:

function Decoder(bytes, port) {
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.
  var value = ((bytes[0] << 8) | bytes[1]) & 0x3fff
  var bat = value / 1000 //Battery,units:V

  var door_open_status = bytes[0] & 0x80 ? 1 : 0 //1:open,0:close
  var water_leak_status = bytes[0] & 0x40 ? 1 : 0

  var mod = bytes[2]
  var alarm = bytes[9] & 0x01

  if (mod == 1) {
    var open_times = (bytes[3] << 16) | (bytes[4] << 8) | bytes[5]
    var open_duration = (bytes[6] << 16) | (bytes[7] << 8) | bytes[8] //units:min
    if (bytes.length == 10 && 0x07 > bytes[0] < 0x0f)
      return {
        BAT_V: bat,
        MOD: mod,
        DOOR_OPEN_STATUS: door_open_status,
        DOOR_OPEN_TIMES: open_times,
        LAST_DOOR_OPEN_DURATION: open_duration,
        ALARM: alarm,
      }
  } else if (mod == 2) {
    var leak_times = (bytes[3] << 16) | (bytes[4] << 8) | bytes[5]
    var leak_duration = (bytes[6] << 16) | (bytes[7] << 8) | bytes[8] //units:min
    if (bytes.length == 10 && 0x07 > bytes[0] < 0x0f)
      return {
        BAT_V: bat,
        MOD: mod,
        WATER_LEAK_STATUS: water_leak_status,
        WATER_LEAK_TIMES: leak_times,
        LAST_WATER_LEAK_DURATION: leak_duration,
      }
  } else if (mod == 3)
    if (bytes.length == 10 && 0x07 > bytes[0] < 0x0f) {
      return {
        BAT_V: bat,
        MOD: mod,
        DOOR_OPEN_STATUS: door_open_status,
        WATER_LEAK_STATUS: water_leak_status,
        ALARM: alarm,
      }
    } else {
      return {
        BAT_V: bat,
        MOD: mod,
      }
    }
}

Create a Flow

To associate the Device with the Decoder Function, go to the Flow panel.

Drag the Device instance and the Function into the field. Connect them with a line from the Device to the Function

Viewing Decoded Device Data

Once you have attached the decoder we can now open the Debug window to view the decoded device payload in the received uplink. To open the Debug window just click on the bug icon on the right side of the device page. Once you have the Debug window open you can wait for the next packet to transmit or force a manual transmission by triggering the sensor with the magnet. You will see the LED flash green while it sends a packet to the network.

Google Sheets log

You can also use the Google Sheet integration to map the decoded data to a Form for recording in sheets. Create a Google Form with Short Answer questions for

  • battery-volts
  • door-open
  • door-open-count
  • last-open-duration
  • alarm

Map it to the Google Sheets Integration and provide this decoder as part of the Sheets setup:

function Decoder(bytes, port) {
  var value = ((bytes[0] << 8) | bytes[1]) & 0x3fff
  var bat = value / 1000 // Battery, units:V
  var door_open_status = bytes[0] & 0x80 ? 1 : 0 // 1:open, 0:close
  var alarm = bytes[9] & 0x01
  var open_times = (bytes[3] << 16) | (bytes[4] << 8) | bytes[5]
  var open_duration = (bytes[6] << 16) | (bytes[7] << 8) | bytes[8] //units:min
  if (bytes.length == 10 && 0x07 > bytes[0] < 0x0f) {
    var decodedPayload = {
      'battery-volts': bat,
      'door-open': door_open_status,
      'door-open-count': open_times,
      'last-open-duration': open_duration,
      alarm: alarm,
    }
    return Serialize(decodedPayload)
  }
}

// Generated: do not touch unless your Google Form fields have changed
var field_mapping = {
  'battery-volts': 'entry.702320693',
  'door-open': 'entry.1934071370',
  'door-open-count': 'entry.844671899',
  'last-open-duration': 'entry.1464236526',
  alarm: 'entry.2127237487',
}
// End Generated

function Serialize(payload) {
  var str = []
  for (var key in payload) {
    if (payload.hasOwnProperty(key)) {
      var name = encodeURIComponent(field_mapping[key])
      var value = encodeURIComponent(payload[key])
      str.push(name + '=' + value)
    }
  }
  return str.join('&')
}

The Sheets integration will provide its own Decoder Function block. Create a new flow from the LDS02 Device, to this Decoder, to the Sheets Integration block.

Notes

Note that the Door Open Duration is a count of full minutes (rounded down) that the door was last open. It does not show the Door Closed time, but repeats the Door Open time for the subsequent Open message.

If door open/close events happen faster than LoRa can send messages (about 3 seconds each), then the door open/close Count will still be correct, and you will see nonsequential values in the Count for missed door events. The last sent message appears to correctly reflect the state of the door, regardless of previously missed messages.

A heartbeat message is automatically sent every 24 hours (+ 5 seconds) when idle, restating the door condition.