Commit 531fb4ef authored by Kristen Thomas's avatar Kristen Thomas

Updated Documentation

Updated documentation to include LoRa examples.
parent 934dfa9b
function Decoder(bytes, port) {
//Payload Formats of LHT65 Deveice
return {
//External sensor
Ext_sensor:
{
"0":"No external sensor",
"1":"Temperature Sensor",
"4":"Interrupt Sensor send",
"5":"Illumination Sensor",
"6":"ADC Sensor",
"7":"Interrupt Sensor count",
}[bytes[6]&0x7F],
//Battery,units:V
BatV:((bytes[0]<<8 | bytes[1]) & 0x3FFF)/1000,
//SHT20,temperature,units:℃
TempC_SHT:((bytes[2]<<24>>16 | bytes[3])/100).toFixed(2),
//SHT20,Humidity,units:%
Hum_SHT:((bytes[4]<<8 | bytes[5])/10).toFixed(1),
//DS18B20,temperature,units:℃
TempC_DS:
{
"1":((bytes[7]<<24>>16 | bytes[8])/100).toFixed(2),
}[bytes[6]&0xFF],
//Exti pin level,PA4
Exti_pin_level:
{
"4":bytes[7] ? "High":"Low",
}[bytes[6]&0x7F],
//Exit pin status,PA4
Exti_status:
{
"4":bytes[8] ? "True":"False",
}[bytes[6]&0x7F],
//BH1750,illumination,units:lux
ILL_lx:
{
"5":bytes[7]<<8 | bytes[8],
}[bytes[6]&0x7F],
//ADC,PA4,units:V
ADC_V:
{
"6":(bytes[7]<<8 | bytes[8])/1000,
}[bytes[6]&0x7F],
//Exti count,PA4,units:times
Exit_count:
{
"7":bytes[7]<<8 | bytes[8],
}[bytes[6]&0x7F],
//Applicable to working mode 4567,and working mode 467 requires short circuit PA9 and PA10
No_connect:
{
"1":"Sensor no connection",
}[(bytes[6]&0x80)>>7],
};
}
\ No newline at end of file
/*
______ _ _______ _______
| ____| | / ____\ \ / / ____|
| |__ | | | (___ \ \_/ / (___
| __| | | \___ \ \ / \___ \
| |____| |____ ____) | | | ____) |
|______|______|_____/ |_| |_____/
ELSYS simple payload decoder.
Use it as it is or remove the bugs :)
www.elsys.se
peter@elsys.se
*/
var TYPE_TEMP = 0x01; //temp 2 bytes -3276.8°C -->3276.7°C
var TYPE_RH = 0x02; //Humidity 1 byte 0-100%
var TYPE_ACC = 0x03; //acceleration 3 bytes X,Y,Z -128 --> 127 +/-63=1G
var TYPE_LIGHT = 0x04; //Light 2 bytes 0-->65535 Lux
var TYPE_MOTION = 0x05; //No of motion 1 byte 0-255
var TYPE_CO2 = 0x06; //Co2 2 bytes 0-65535 ppm
var TYPE_VDD = 0x07; //VDD 2byte 0-65535mV
var TYPE_ANALOG1 = 0x08; //VDD 2byte 0-65535mV
var TYPE_GPS = 0x09; //3bytes lat 3bytes long binary
var TYPE_PULSE1 = 0x0A; //2bytes relative pulse count
var TYPE_PULSE1_ABS = 0x0B; //4bytes no 0->0xFFFFFFFF
var TYPE_EXT_TEMP1 = 0x0C; //2bytes -3276.5C-->3276.5C
var TYPE_EXT_DIGITAL = 0x0D; //1bytes value 1 or 0
var TYPE_EXT_DISTANCE = 0x0E; //2bytes distance in mm
var TYPE_ACC_MOTION = 0x0F; //1byte number of vibration/motion
var TYPE_IR_TEMP = 0x10; //2bytes internal temp 2bytes external temp -3276.5C-->3276.5C
var TYPE_OCCUPANCY = 0x11; //1byte data
var TYPE_WATERLEAK = 0x12; //1byte data 0-255
var TYPE_GRIDEYE = 0x13; //65byte temperature data 1byte ref+64byte external temp
var TYPE_PRESSURE = 0x14; //4byte pressure data (hPa)
var TYPE_SOUND = 0x15; //2byte sound data (peak/avg)
var TYPE_PULSE2 = 0x16; //2bytes 0-->0xFFFF
var TYPE_PULSE2_ABS = 0x17; //4bytes no 0->0xFFFFFFFF
var TYPE_ANALOG2 = 0x18; //2bytes voltage in mV
var TYPE_EXT_TEMP2 = 0x19; //2bytes -3276.5C-->3276.5C
var TYPE_EXT_DIGITAL2 = 0x1A; // 1bytes value 1 or 0
var TYPE_EXT_ANALOG_UV= 0x1B; // 4 bytes signed int (uV)
var TYPE_DEBUG = 0x3D; // 4bytes debug
function bin16dec(bin) {
var num=bin&0xFFFF;
if (0x8000 & num)
num = - (0x010000 - num);
return num;
}
function bin8dec(bin) {
var num=bin&0xFF;
if (0x80 & num)
num = - (0x0100 - num);
return num;
}
function hexToBytes(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
function DecodeElsysPayload(data){
var obj = new Object();
for(i=0;i<data.length;i++){
//console.log(data[i]);
switch(data[i]){
case TYPE_TEMP: //Temperature
var temp=(data[i+1]<<8)|(data[i+2]);
temp=bin16dec(temp);
obj.temperature=temp/10;
i+=2;
break
case TYPE_RH: //Humidity
var rh=(data[i+1]);
obj.humidity=rh;
i+=1;
break
case TYPE_ACC: //Acceleration
obj.x=bin8dec(data[i+1]);
obj.y=bin8dec(data[i+2]);
obj.z=bin8dec(data[i+3]);
i+=3;
break
case TYPE_LIGHT: //Light
obj.light=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_MOTION: //Motion sensor(PIR)
obj.motion=(data[i+1]);
i+=1;
break
case TYPE_CO2: //CO2
obj.co2=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_VDD: //Battery level
obj.vdd=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_ANALOG1: //Analog input 1
obj.analog1=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_GPS: //gps
obj.lat=(data[i+1]<<16)|(data[i+2]<<8)|(data[i+3]);
obj.long=(data[i+4]<<16)|(data[i+5]<<8)|(data[i+6]);
i+=6;
break
case TYPE_PULSE1: //Pulse input 1
obj.pulse1=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_PULSE1_ABS: //Pulse input 1 absolute value
var pulseAbs=(data[i+1]<<24)|(data[i+2]<<16)|(data[i+3]<<8)|(data[i+4]);
obj.pulseAbs=pulseAbs;
i+=4;
break
case TYPE_EXT_TEMP1: //External temp
var temp=(data[i+1]<<8)|(data[i+2]);
temp=bin16dec(temp);
obj.externalTemperature=temp/10;
i+=2;
break
case TYPE_EXT_DIGITAL: //Digital input
obj.digital=(data[i+1]);
i+=1;
break
case TYPE_EXT_DISTANCE: //Distance sensor input
obj.distance=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_ACC_MOTION: //Acc motion
obj.accMotion=(data[i+1]);
i+=1;
break
case TYPE_IR_TEMP: //IR temperature
var iTemp=(data[i+1]<<8)|(data[i+2]);
iTemp=bin16dec(iTemp);
var eTemp=(data[i+3]<<8)|(data[i+4]);
eTemp=bin16dec(eTemp);
obj.irInternalTemperature=iTemp/10;
obj.irExternalTemperature=eTemp/10;
i+=4;
break
case TYPE_OCCUPANCY: //Body occupancy
obj.occupancy=(data[i+1]);
i+=1;
break
case TYPE_WATERLEAK: //Water leak
obj.waterleak=(data[i+1]);
i+=1;
break
case TYPE_GRIDEYE: //Grideye data
var ref = data[i+1];
i++;
obj.grideye = [];
for(var j = 0; j < 64; j++) {
obj.grideye[j] = ref + (data[1+i+j] / 10.0);
}
i += 64;
break
case TYPE_PRESSURE: //External Pressure
var temp=(data[i+1]<<24)|(data[i+2]<<16)|(data[i+3]<<8)|(data[i+4]);
obj.pressure=temp/1000;
i+=4;
break
case TYPE_SOUND: //Sound
obj.soundPeak=data[i+1];
obj.soundAvg=data[i+2];
i+=2;
break
case TYPE_PULSE2: //Pulse 2
obj.pulse2=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_PULSE2_ABS: //Pulse input 2 absolute value
obj.pulseAbs2=(data[i+1]<<24)|(data[i+2]<<16)|(data[i+3]<<8)|(data[i+4]);
i+=4;
break
case TYPE_ANALOG2: //Analog input 2
obj.analog2=(data[i+1]<<8)|(data[i+2]);
i+=2;
break
case TYPE_EXT_TEMP2: //External temp 2
var temp=(data[i+1]<<8)|(data[i+2]);
temp=bin16dec(temp);
if(typeof obj.externalTemperature2 === "number") {
obj.externalTemperature2 = [obj.externalTemperature2];
}
if(typeof obj.externalTemperature2 === "object") {
obj.externalTemperature2.push(temp / 10);
} else {
obj.externalTemperature2 = temp / 10;
}
i+=2;
break
case TYPE_EXT_DIGITAL2: //Digital input 2
obj.digital2=(data[i+1]);
i+=1;
break
case TYPE_EXT_ANALOG_UV: //Load cell analog uV
obj.analogUv = (data[i + 1] << 24) | (data[i + 2] << 16) | (data[i + 3] << 8) | (data[i + 4]);
i += 4;
break
default: //somthing is wrong with data
i=data.length;
break
}
}
return obj;
}
function Decoder(bytes, port) {
return DecodeElsysPayload(bytes);
}
\ No newline at end of file
function Decoder(bytes, port) {
if (bytes[0] === 0x01 && bytes[1] === 0x04 && bytes[2] === 0x01) {
// decode as shown in earlier post
var battery = (bytes[3] / 10);
var light = (bytes[4] << 8) | bytes[5];
return {
battery: battery,
light: light,
};
}
}
\ No newline at end of file
......@@ -83,6 +83,7 @@ here.
adding-buildings-and-sensors
multiple-organizations
setting-up-sensors-to-post-to-bmon
setting-up-lora-sensors-to-post-to-bmon
multi-building-charts
sensor-alerts
creating-a-dashboard
......
......@@ -290,7 +290,7 @@ for every remote sensor associated with the thermostat. Remote Sensors
are not supported by the Ecobee3 Lite thermostat.
Collect Data from Devices with a MODBUS TCP Inteface
--------------------------------------------------
-----------------------------------------------------
A BMON Periodic Script is available to collect data from devices that have
a `MODBUS TCP <https://en.wikipedia.org/wiki/Modbus>`_ interface, such as
......@@ -386,7 +386,7 @@ the variable ``val`` in the function holds the raw holding register value. In
this example, the transform function is ``val/10``, so the holding register
value is divided by 10 before being stored in BMON. All Python math operators
are available, including all of the functions present in the
`math <https://docs.python.org/2/library/math.html`_ such as ``sin()`` and
`math <https://docs.python.org/2/library/math.html>`_ such as ``sin()`` and
``log()``.
Collect Data from a Sensaphone IMS-4000 Monitoring System
......@@ -528,7 +528,7 @@ section of the :ref:`adding-buildings-and-sensors` document.
There is also a special ``Calculated Field`` function available that can
create a Sensor that estimates the pellet consumption or heat output of
the boiler by examining the Status (P241 parameter number) sensor of the
boiler. See the :ref:`calculated-fields` document for more details.
boiler. See the :ref:`calculated fields <calculated-fields>` document for more details.
Collect Data from Enphase Solar PV Systems
------------------------------------------
......
.. _setting-up-lora-sensors-to-post-to-bmon:
Setting Up LoRa Sensors to Post to BMON
=========================================
This page gives specific instructions on how to set up LoRa
sensors to post their data to a BMON system. In
addition, general documentation has been provided on how to set up a LoRaWan
communication Gateway and creating payload applications for LoRa sensors
in `The Things Network <https://www.thethingsnetwork.org>`_ (TTN) which integrates
with your BMON system.
#######################################################
Before you Begin - First time The Things Network Setup
#######################################################
Skip to step 6 `Register Your Device`_ if you already have a preexisting TTN account and application configured for the device type.
#. Visit `TTN <https://account.thethingsnetwork.org/register>`_ and create a free account
#. `Add your LoRa Gateway to TTN`_
#. `Create an Application in TTN`_ for each sensor type/manufacturer
#. `Add an HTTP integration for BMON`_
#. `Add a payload decoder to TTN`_ for the sensor
#. `Register Your Device`_
.. note:: You typically only need to create *one* application per device manufacturer - many manufacturers use a unified payload format across their devices though some may write custom payload decoders by device, see your sensor documentation for more information.
**Add your LoRa Gateway to TTN**
----------------------------------
The gateway will require some general setup that is not covered in this documentation as it has been thoroughly documented by The Things Network and is also unique to your make/manufacturer's LoRa Gateway hardware.
The general setup for a gateway in the United States (west coast) will look similar to this in TTN
.. image:: /_static/ttn_gateway.jpg
* `Instructions for adding a Laird LoRa Gateway to TTN <https://www.thethingsnetwork.org/docs/gateways/laird/>`_
* `Instructions for adding a The Things Indoor Gateway to TTN <https://www.thethingsnetwork.org/docs/gateways/thethingsindoor/>`_
* `More gateways on TTN <https://www.thethingsnetwork.org/docs/gateways/>`_
**Create an Application in TTN**
--------------------------------
* Following the `TTN documentation <https://www.thethingsnetwork.org/docs/applications/add.html>`_ create an ``Application`` for each sensor/type you have
* Here is an example of a Dragino Application
.. image:: /_static/ttn_app_overview2.jpg
.. note:: you can select ``manage euis`` from this page to add the specific EUI provided by the device manufacturer, this EUI will be the same for every sensor of this type. Adding the EUI at this level means you don't have to enter it for each device during registration, simply make sure it is selected when registering your device later.
**Add an HTTP integration for BMON**
----------------------------------------
* With the application you just made still open in TTN, click the ``Integrations`` tab
* Next, select ``add integration``
* From the list of options, select ``HTTP Integration``
* Here is an example Dragino integration
.. image:: /_static/ttn_html_integration.jpg
where:
* ``Process ID:`` by using bmon-dragino here we can easily tell from a glance that the process is used for BMON and is for the Dragino sensor.
* ``Access Key:`` select *default key [devices] [messages]*
* ``URL:`` You should use your BMON url/readingdb/reading/store-things/ ex. http://bms.ahfc.us/readingdb/reading/store-things/
* ``Method:`` select POST as this is a data posting event
* ``Authorization:`` leave blank
* ``Custom Header Name:`` use *store-key* here
* ``Custom Header Value:`` Your *BMSAPP_STORE_KEY* from ``settings.py``
**Add a payload decoder to TTN**
------------------------------------
* Locate the payload decoder for your device, or write your own depending on your needs
* With the correct sensor application open in TTN, click the ``Payload Formats`` tab
* Select ``Custom`` for ``Payload Format``
* Make sure the ``decoder`` tab is selected and paste the contents of your payload decoder into the code field
* Scroll down and click ``save``
.. image:: /_static/ttn_dragino_payload.jpg
**Payload Decoders**
* `Dragino Downloads <http://www.dragino.com/downloads/downloads/>`_
* `Dragino LHT65 official payload decoder <http://www.dragino.com/downloads/downloads/LHT65/payload_decode/ttn_payload_decode.txt>`_
* :download:`Dragino decoder </_static/dragino_payload.txt>` (locally hosted)
* `Elsys official payload decoder (scroll to TheThingsNetwork decoder) <https://www.elsys.se/en/elsys-payload/>`_
* :download:`Elsys decoder </_static/elsys_payload.txt>` (locally hosted)
* :download:`Netvox Lux decoder </_static/netvox_lux_payload.txt>` (locally hosted)
**Register Your Device**
-------------------------
* Navigate back to the relevant application for your device (ex. Dragino)
* With the application open, click the ``Integrations`` tab
* Next, select ``register device``
* Using information provided by the sensor manufacturer, complete the device registration form
.. image:: /_static/ttn_register_device.jpg
* For ``Device ID`` you can make up an ID tough it helps to quickly identify the device later on by using a naming convention like: lht65-a84041000181c74e, with LHT65 as the Dragino sensor model, and the long string is the Device EUI.
* ``Device EUI`` is generally printed on the sensor.
* ``App Key`` is the secret key that also comes with the sensor (typically on a separate document)
* ``App EUI`` should be the same for **every** sensor of this type. It should also be included with the sensor. You can enter it at the Application level, and it will show up here as a default.
* TTN likes to to generate it's own EUI here if you haven't already entered one, overwrite this function by clicking the edit "pencil" icon
#################################
Adding Your LoRa Device to BMON
#################################
The beauty of this system is that as soon as the HTTP integration is made for BMON and the sensors start reporting to the gateway connected to TTN you'll start seeing your sensors in BMON almost immediately.
Here is an example Dragnio LHT65 sensor taken from the `unassigned-sensors` page of a BMON site once the TTN HTTP integration started communicating with BMON.
.. image:: /_static/bmon_lora_ex.jpg
* ``A84041##########_BatV`` - common on most LoRa sensors, BatV indicates the sensor's battery in Voltage
* ``A84041##########_rssi`` - common on most LoRa sensors, rssi indicates the sensor's received signal strength indicator. The higher the RSSI value, the stronger the signal. When measured in negative numbers, the number that is closer to zero usually means better signal.
* ``A84041##########_snr`` - common on most LoRa sensors, snr indicates the signal-to-noise ratio
* ``A84041##########_Hum_SHT`` - Dragino Humidity
* ``A84041##########_TempC_DS`` - Dragino external probe Temperature (C)
* ``A84041##########_TempC_SHT`` - Dragnio internal Temperature (C)
`Follow these instructions to add your sensor to the BMON system <adding-buildings-and-sensors.html#adding-sensors>`_.
########################
Resources
########################
* `Laird Sentrius RG1xx LoRaWAN Gateway <https://www.lairdconnect.com/wireless-modules/lorawan-solutions/sentrius-rg1xx-lorawan-gateway-wi-fi-ethernet-optional-lte-us-only/>`_
* `Dragino LHT65 Temperature and Humidity sensor <http://www.dragino.com/products/lora-lorawan-end-node/item/151-lht65.html>`_
* `Elsys ERS CO2/Lux/PIR/Temperature/Humidity Sensor <https://www.elsys.se/shop/product/ers-co2/?v=7516fd43adaa>`_
* `Netvox R311G Lux Sensor <http://www.netvox.com.tw/product.asp?pro=R311G>`_
* For further information and discussion on LoRa equipment visit the `BMON forum <https://forum.bmon.org/c/hardware/lora/11>`_
......@@ -49,6 +49,13 @@ A few different sensor types have been set up to work with BMON (e.g.
have access to the Internet can be configured to work with BMON. This
document gives details on how to set up sensors in the system.
:ref:`Setting Up LoRa Sensors to Post to BMON`
-----------------------------------------------
A page dedicated to LoRaWan sensor types that have been set up to work with BMON
including basic information on integrating with `The Things Network <http://thethingsnetwork.org>`_,
payload decoders, gateways, and sensor configurations.
:ref:`Multi-Building Charts <multi-building-charts>`
----------------------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment