Skip to content

Instantly share code, notes, and snippets.

@Bwooce
Created June 27, 2021 11:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bwooce/146e55d294a017614183ff559f591e10 to your computer and use it in GitHub Desktop.
Save Bwooce/146e55d294a017614183ff559f591e10 to your computer and use it in GitHub Desktop.
#include "LoRaWan_APP.h"
#include "Arduino.h"
/*
set LoraWan_RGB to Active,the RGB active in loraWan
RGB red means sending;
RGB purple means joined done;
RGB blue means RxWindow1;
RGB yellow means RxWindow2;
RGB green means received done;
*/
/* OTAA para*/
uint8_t devEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 };
uint8_t appEui[] = { 0x32, 0x22, 0x00, 0x00, 0x88, 0x00, 0x88, 0x00 };
uint8_t appKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 };
/* ABP para*/
uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda, 0x85 };
uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef, 0x67 };
uint32_t devAddr = ( uint32_t )0x007e6ae1;
/*LoraWan channelsmask, default channels 0-7*/
uint16_t userChannelsMask[6] = { 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
/*LoraWan region, select in arduino IDE tools*/
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
/*LoraWan Class, Class A and Class C are supported*/
DeviceClass_t loraWanClass = LORAWAN_CLASS;
/*the application data transmission duty cycle. value in [ms].*/
uint32_t appTxDutyCycle = 1 * 60 * 60 * 1000;
/*OTAA or ABP*/
bool overTheAirActivation = LORAWAN_NETMODE;
/*ADR enable*/
bool loraWanAdr = LORAWAN_ADR;
/* set LORAWAN_Net_Reserve ON, the node could save the network info to flash, when node reset not need to join again */
bool keepNet = LORAWAN_NET_RESERVE;
/* Indicates if the node is sending confirmed or unconfirmed messages */
bool isTxConfirmed = LORAWAN_UPLINKMODE;
/* Application port */
uint8_t appPort = 2;
/*!
Number of trials to transmit the frame, if the LoRaMAC layer did not
receive an acknowledgment. The MAC performs a datarate adaptation,
according to the LoRaWAN Specification V1.0.2, chapter 18.4, according
to the following table:
Transmission nb | Data Rate
----------------|-----------
1 (first) | DR
2 | DR
3 | max(DR-1,0)
4 | max(DR-1,0)
5 | max(DR-2,0)
6 | max(DR-2,0)
7 | max(DR-3,0)
8 | max(DR-3,0)
Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
the datarate, in case the LoRaMAC layer did not receive an acknowledgment
*/
uint8_t confirmedNbTrials = 4;
const int mailPin = GPIO1;
const int doorPin = GPIO2;
bool doorWoke = false;
bool doorOpen = false;
bool mailWoke = false;
bool mailOpen = false;
const int limitSendMillis = 60 * 1000; // don't send transitions more than once a minute
int lastSend = 0;
int mapBatteryVoltageToLevel(int x, int in_min, int in_max, int out_min, int out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
/* Prepares the payload of the frame */
static bool prepareTxFrame(uint8_t port) {
/*appData size is LORAWAN_APP_DATA_MAX_SIZE which is defined in "commissioning.h".
appDataSize max value is LORAWAN_APP_DATA_MAX_SIZE.
if enabled AT, don't modify LORAWAN_APP_DATA_MAX_SIZE, it may cause system hanging or failure.
if disabled AT, LORAWAN_APP_DATA_MAX_SIZE can be modified, the max value is reference to lorawan region and SF.
for example, if use REGION_CN470,
the max value for different DR can be found in MaxPayloadOfDatarateCN470 refer to DataratesCN470 and BandwidthsCN470 in "RegionCN470.h".
*/
// reset the internal state to the actual state, avoiding any dead states
doorOpen = digitalRead(doorPin);
mailOpen = digitalRead(mailPin);
uint16_t batteryVoltage = getBatteryVoltage();
uint8_t batteryLevel = mapBatteryVoltageToLevel(batteryVoltage, 3600, 4200, 0, 100);
appDataSize = 5;
appData[0] = doorOpen;
appData[1] = mailOpen;
appData[2] = highByte(batteryVoltage);
appData[3] = lowByte(batteryVoltage);
appData[4] = batteryLevel;
//Serial.print(F("Battery Voltage: "));
//Serial.println(batteryVoltage);
//Serial.print(F("Battery Level: "));
//Serial.println(batteryLevel);
}
void doorWakeup() {
// let the state settle
delay(10);
// avoid duplicate interrupts retriggering a packet send, and re-read the pin state
// to avoid detecting spurious transitions due to noise induced on the wires
if (!doorOpen && digitalRead(doorPin) == HIGH) { // was closed, now open
doorOpen = true;
doorWoke = true;
} else if (doorOpen && digitalRead(doorPin) == LOW) { // was open, now closed
doorOpen = false;
doorWoke = true;
}
}
void mailWakeup() {
delay(10);
if (!mailOpen && digitalRead(mailPin) == HIGH) { // was closed, now open
mailOpen = true;
mailWoke = true;
} else if (mailOpen && digitalRead(mailPin) == LOW) { // was open, now closed
mailOpen = false;
mailWoke = true;
}
}
void setup() {
Serial.begin(115200);
pinMode(mailPin, INPUT_PULLUP);
pinMode(doorPin, INPUT_PULLUP);
#if(AT_SUPPORT)
enableAt();
#endif
deviceState = DEVICE_STATE_INIT;
LoRaWAN.ifskipjoin();
doorWoke = false;
mailWoke = false;
attachInterrupt(mailPin, mailWakeup, BOTH);
attachInterrupt(doorPin, doorWakeup, BOTH);
lastSend = millis();
}
void loop() {
switch (deviceState) {
case DEVICE_STATE_INIT:
{
#if(LORAWAN_DEVEUI_AUTO)
LoRaWAN.generateDeveuiByChipID();
#endif
#if(AT_SUPPORT)
getDevParam();
#endif
printDevParam();
LoRaWAN.init(loraWanClass, loraWanRegion);
deviceState = DEVICE_STATE_JOIN;
break;
}
case DEVICE_STATE_JOIN:
{
LoRaWAN.join();
break;
}
case DEVICE_STATE_SEND:
{
prepareTxFrame(appPort);
LoRaWAN.send();
deviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_CYCLE:
{
// Schedule next packet transmission
txDutyCycleTime = appTxDutyCycle + randr( 0, APP_TX_DUTYCYCLE_RND );
LoRaWAN.cycle(txDutyCycleTime);
deviceState = DEVICE_STATE_SLEEP;
break;
}
case DEVICE_STATE_SLEEP:
{
if (doorWoke || mailWoke) {
if (IsLoRaMacNetworkJoined) {
Serial.print("doorPin: ");
Serial.println(digitalRead(doorPin));
Serial.print("mailPin: ");
Serial.println(digitalRead(mailPin));
if(lastSend + limitSendMillis < millis() || lastSend > millis()) { // account for millis wrapping
Serial.println("Transmitting LoRaWAN");
prepareTxFrame(appPort);
LoRaWAN.send();
} else {
Serial.println("Skipping LoRaWAN send due to transition send limit");
}
}
doorWoke = false;
mailWoke = false;
}
Serial.println("going back to sleep...");
LoRaWAN.sleep();
break;
}
default:
{
deviceState = DEVICE_STATE_INIT;
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment