pull/19/head
Louis Thiery 2020-04-24 09:31:24 -07:00 zatwierdzone przez GitHub
rodzic d48d6df55f
commit 335d98170f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 337 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,74 @@
# ST B-L072Z-LRWAN1 - Button to AWS Example
This is an example code for building an AWS IoT application that sends you text messages using Twilio.
You'll need:
* ST-B-L072Z-LRWAN1
* An AWS account
* A Twilio account
You need to load this sketch onto the ST-B-L072Z-LRWAN1. The sketch will send a heartbeat every 15 seconds and will asyncronously send an alert whenever the button is pressed.
Once you confirm that the device is connecting and sending data via Helium Console, you'll want to setup an integration to AWS IoT.
Once you do that, you want to create a Lambda function using the Python file here: lambda_button_text.py
You'll need to set environmental variables to make it work:
* TWILIO_AUTH_TOKEN: get this from your Twilio dashboard
* TWILIO_ACCOUNT_SID: get this from your Twilio dashboard
* TWILIO_ASSIGNED_NUMBER: get this from your Twilio dashboard
* USER_NUMBER: this is the cell phone number which will get text message alerts when the button is pressed
Once you save the lambda function, you will simply need to connect the lambda function to an AWS IoT trigger. Use the rule query statement: SELECT * FROM "helium"
Now you're done! Press the button and you should get a text message.
## Required Arduino Libraries
From the Arduino IDE, open the Library Manager (Sketch->Include Library->Manage Libraries). In the search box, type the library name below and install the latest version.
[MCCI Arduino LoRaWAN Library](https://github.com/mcci-catena/arduino-lmic)
## Required Arduino Board Support
### B-L072Z-LRWAN1 - ST STM32L0 Discovery kit
Install board support package, find instructions [here](https://github.com/stm32duino/Arduino_Core_STM32#getting-started).
Arduino IDE:
1. Select Tools -> Board: -> Discovery
2. Select Tools -> Board part number: -> Discovery L072Z-LRWAN1
## Required Hardware
### B-L072Z-LRWAN1 - ST STM32L0 Discovery kit
[B-L072Z-LRWAN1 Product Page](https://www.st.com/en/evaluation-tools/b-l072z-lrwan1.html)
[B-L072Z-LRWAN1 User Manual](https://www.st.com/content/ccc/resource/technical/document/user_manual/group0/ac/62/15/c7/60/ac/4e/9c/DM00329995/files/DM00329995.pdf/jcr:content/translations/en.DM00329995.pdf)
## Programming (Uploading Method):
#### STM32CubeProgrammer(SWD)
Will use onboard ST-Link(Flasher/Debugger) to upload sketch.
Download and Install required utility from ST [here](https://www.st.com/en/development-tools/stm32cubeprog.html).
Arduino IDE:
Select Tools -> Upload Method -> STM32CubeProgrammer(SWD)
### PlatformIO Support
The PlatformIO Board file for this board is currently using the incorrect OpenOCD (Upload/Debug)
script for the microcontroller on this board. We are in the process of pushing a fix upstream. When
uploading or debugging, hold the reset button down right until the upload or debug process initiates
it's routine in communicating with the board, this seems to aleviate the issue for right now.
`platformio.ini`
```
[env:disco_l072cz_lrwan1]
platform = ststm32
board = disco_l072cz_lrwan1
framework = arduino
lib_deps =
MCCI LoRaWAN LMIC library
CayenneLPP
```

Wyświetl plik

@ -0,0 +1,27 @@
import base64
import json
import os
from botocore.vendored import requests
TWILIO_ACCOUNT_SID = os.environ.get("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.environ.get("TWILIO_AUTH_TOKEN")
TWILIO_SMS_URL = "https://api.twilio.com/2010-04-01/Accounts/" + TWILIO_ACCOUNT_SID + "/Messages.json"
TWILIO_ASSIGNED_NUMBER = os.environ.get("TWILIO_ASSIGNED_NUMBER")
USER_NUMBER = os.environ.get("USER_NUMBER")
def lambda_handler(event, context):
byte_arr = list(base64.b64decode(event['payload']))
if byte_arr[0] == 1 :
to_number =USER_NUMBER
from_number = TWILIO_ASSIGNED_NUMBER
body = "Button pressed!"
data = {"To": to_number, "From": from_number, "Body": body}
response = requests.post(TWILIO_SMS_URL, data = data, auth=(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN))
print(response.text)
return "Button pushed - Message Sent"
else:
print("Heartbeat")
return "Heartbeat"

Wyświetl plik

@ -0,0 +1,236 @@
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
// This should also be in little endian format
static const u1_t PROGMEM DEVEUI[8]= { FILL_ME_IN };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This should also be in little endian format
static const u1_t PROGMEM APPEUI[8]= { FILL_ME_IN };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This key should be in big endian format
static const u1_t PROGMEM APPKEY[16] = { FILL_ME_IN };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
static uint8_t mydata[] = {0};
static osjob_t sendjob;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 15;
// Pin mapping
#include "arduino_lmic_hal_boards.h"
// Pin mapping Discovery
const lmic_pinmap lmic_pins = *Arduino_LMIC::GetPinmap_Disco_L072cz_Lrwan1();
void printHex2(unsigned v) {
v &= 0xff;
if (v < 16)
Serial.print('0');
Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("AppSKey: ");
for (size_t i=0; i<sizeof(artKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(artKey[i]);
}
Serial.println("");
Serial.print("NwkSKey: ");
for (size_t i=0; i<sizeof(nwkKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(nwkKey[i]);
}
Serial.println();
}
// Disable link check validation (automatically enabled
// during join, but because slow data rates change max TX
// size, we don't use it in this example.
LMIC_setLinkCheckMode(0);
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_RFU1:
|| Serial.println(F("EV_RFU1"));
|| break;
*/
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.println(F("Received "));
Serial.println(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_SCAN_FOUND:
|| Serial.println(F("EV_SCAN_FOUND"));
|| break;
*/
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.print(F("Unknown event: "));
Serial.println((unsigned) ev);
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending update packet"));
} else {
mydata[0] = 0;
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata), 0);
Serial.println(F("Packet queued: Update Send"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
bool async_send(){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending async send yet"));
return true;
} else {
mydata[0] = 1;
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata), 0);
Serial.println(F("Packet queued: Async Send"));
return false;
}
// Next TX is scheduled after TX_COMPLETE event.
}
static volatile bool button_pushed;
void push_button_ISR(){
button_pushed = true;
}
void setup() {
Serial.begin(9600);
Serial.println("Starting");
SPI.setMOSI(RADIO_MOSI_PORT);
SPI.setMISO(RADIO_MISO_PORT);
SPI.setSCLK(RADIO_SCLK_PORT);
SPI.setSSEL(RADIO_NSS_PORT);
// Configure User Button
pinMode(USER_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(USER_BTN), push_button_ISR, HIGH);
Serial.println("Setup Complete");
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// allow much more clock error than the X/1000 default. See:
// https://github.com/mcci-catena/arduino-lorawan/issues/74#issuecomment-462171974
// https://github.com/mcci-catena/arduino-lmic/commit/42da75b56#diff-16d75524a9920f5d043fe731a27cf85aL633
// the X/1000 means an error rate of 0.1%; the above issue discusses using values up to 10%.
// so, values from 10 (10% error, the most lax) to 1000 (0.1% error, the most strict) can be used.
LMIC_setClockError(1 * MAX_CLOCK_ERROR / 40);
LMIC_setLinkCheckMode(0);
LMIC_setDrTxpow(DR_SF7,14);
LMIC_selectSubBand(6);
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}
void loop() {
if(button_pushed) {
button_pushed = async_send();
}
os_runloop_once();
}