msv-clubhouse-node/README.md

3.4 KiB

msv-clubhouse-node

  • Work in progress !
  • Technical demo

Overview

architecture diagram

Hardware

Register Device at TTN

  1. Register manually a device.
  2. Frequency plan Europe 863-870 MHz (SF9 for RX2 - recommended)
  3. LoRaWAN version LoRaWAN Specification 1.0.2
  4. Regional Parameters version RP001 Regional Parameters 1.0.2
  5. JoinEUI all zeros
  6. Generate keys

Build Node Firmware

  1. Clone repo
  2. Init GIT-submodules
git submodule init
git submodule update
  1. Set following defines via menuconfig:
AppEUI
DevEUI
AppKey
TTN LoRa frequency / region
  1. Build with ESP-IDF extension in VSCodium

MQTT Endpoint

pip3 install paho-mqtt

  • mkdir /opt/msv-clubhouse-backend/
  • cd /opt/msv-clubhouse-backend/
  • import msv_clubhouse_backend.py and config.py
  • Set the constants in config.py
  • chmod +x /opt/msv-clubhouse-backend/msv_clubhouse_backend.py
  • chown -R prometheus /opt/msv-clubhouse-backend/
  • nano /etc/systemd/system/msv-clubhouse-backend.service
  • systemctl daemon-reload && systemctl enable --now msv-clubhouse-backend.service

JS Payload Formatter

function Decoder(bytes, port) {
  var decoded = {};
  
  // temperature 
  rawTemp = bytes[0] + bytes[1] * 256;
  decoded.degreesC = sflt162f(rawTemp) * 100;
  
  // pressure 
  rawPressure = bytes[2] + bytes[3] * 256;
  decoded.pressure = sflt162f(rawPressure) * 100;
  
  // windspeed 
  rawWindspeed = bytes[4] + bytes[5] * 256;
  decoded.windspeed = sflt162f(rawWindspeed) * 100;
  
  // winddirection 
  rawWinddirection = bytes[6] + bytes[7] * 256;
  decoded.winddirection = sflt162f(rawWinddirection) * 100;
  
  if(bytes[8] === 0){
    decoded.dooropen = false;
  }else{
    decoded.dooropen = true;
  }
  
  
  return decoded;
}

function sflt162f(rawSflt16)
	{
	// rawSflt16 is the 2-byte number decoded from wherever;
	// it's in range 0..0xFFFF
	// bit 15 is the sign bit
	// bits 14..11 are the exponent
	// bits 10..0 are the the mantissa. Unlike IEEE format, 
	// 	the msb is transmitted; this means that numbers
	//	might not be normalized, but makes coding for
	//	underflow easier.
	// As with IEEE format, negative zero is possible, so
	// we special-case that in hopes that JavaScript will
	// also cooperate.
	//
	// The result is a number in the open interval (-1.0, 1.0);
	// 
	
	// throw away high bits for repeatability.
	rawSflt16 &= 0xFFFF;

	// special case minus zero:
	if (rawSflt16 == 0x8000)
		return -0.0;

	// extract the sign.
	var sSign = ((rawSflt16 & 0x8000) !== 0) ? -1 : 1;
	
	// extract the exponent
	var exp1 = (rawSflt16 >> 11) & 0xF;

	// extract the "mantissa" (the fractional part)
	var mant1 = (rawSflt16 & 0x7FF) / 2048.0;

	// convert back to a floating point number. We hope 
	// that Math.pow(2, k) is handled efficiently by
	// the JS interpreter! If this is time critical code,
	// you can replace by a suitable shift and divide.
	var f_unscaled = sSign * mant1 * Math.pow(2, exp1 - 15);

	return f_unscaled;
	}

Grafana Dashboard

see frontend/

screenshot of grafana-dashboard