diff --git a/Makefile b/Makefile index bdd0f08..06f1b7a 100644 --- a/Makefile +++ b/Makefile @@ -128,7 +128,7 @@ $(OUT)$(NAME).elf: protobufg bin $(OBJDIRS) $(OBJS) $(CC) $(CFLAGS) -o $(OUT)$(NAME).elf collar.cpp $(INC_DIRS) $(OBJS) test: - g++ -o $(OUT)test prototest.cpp $(INC_DIRS) $(SRC_FILES_COMMON) + g++ -o $(OUT)test test.c $(INC_DIRS) $(SRC_FILES_COMMON) $(OUT)test protobufg: diff --git a/collar.cpp b/collar.cpp index 5c17b90..e44b643 100644 --- a/collar.cpp +++ b/collar.cpp @@ -1,18 +1,30 @@ -// Hello LoRa - ABP TTN Packet Sender (Multi-Channel) -// Tutorial Link: https://learn.adafruit.com/the-things-network-for-feather/using-a-feather-32u4 -// -// Adafruit invests time and resources providing this open source code. -// Please support Adafruit and open source hardware by purchasing -// products from Adafruit! -// -// Copyright 2015, 2016 Ideetron B.V. -// -// Modified by Brent Rubell for Adafruit Industries, 2018 -/************************** Configuration ***********************************/ +/******************************************************************************* + * The Things Network - ABP Feather + * + * Example of using an Adafruit Feather M0 and DHT22 with a + * single-channel TheThingsNetwork gateway. + * + * This uses ABP (Activation by Personalization), where session keys for + * communication would be assigned/generated by TTN and hard-coded on the device. + * + * Learn Guide: https://learn.adafruit.com/lora-pi + * + * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman + * Copyright (c) 2018 Terry Moore, MCCI + * Copyright (c) 2018 Brent Rubell, Adafruit Industries + * + * Permission is hereby granted, free of charge, to anyone + * obtaining a copy of this document and accompanying files, + * to do whatever they want with them without any restriction, + * including, but not limited to, copying, modification and redistribution. + * NO WARRANTY OF ANY KIND IS PROVIDED. + *******************************************************************************/ +#include +#include +#include #include #include -#include -#include + #include "Base64.h" #include "gateway/message.pb.h" @@ -21,26 +33,75 @@ #include "pb_encode.h" #include "pb_decode.h" +#include "lmic_project_config.h" #include "gateway/message.pb.h" -// Visit your thethingsnetwork.org device console -// to create an account, or if you need your session keys. +// DHT digital pin and sensor type +#define DHTPIN 10 +#define DHTTYPE DHT22 -// Network Session Key (MSB) -uint8_t NwkSkey[16] = {0x52, 0x92, 0xC0, 0x72, 0x2D, 0x3C, 0x55, 0x5E, 0xE4, 0xB9, 0x9E, 0x9B, 0x88, 0x66, 0x47, 0xF1}; +// +// For normal use, we require that you edit the sketch to replace FILLMEIN +// with values assigned by the TTN console. However, for regression tests, +// we want to be able to compile these scripts. The regression tests define +// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non- +// working but innocuous value. +// +/* +#ifdef COMPILE_REGRESSION_TEST +# define FILLMEIN 0 +#else +# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!" +# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN) +#endif +*/ +// LoRaWAN NwkSKey, network session key +static const PROGMEM u1_t NWKSKEY[16] = { 0x52, 0x92, 0xC0, 0x72, 0x2D, 0x3C, 0x55, 0x5E, 0xE4, 0xB9, 0x9E, 0x9B, 0x88, 0x66, 0x47, 0xF1 }; -// Application Session Key (MSB) -uint8_t AppSkey[16] = {0xC4, 0x30, 0xEF, 0x56, 0x4F, 0x6D, 0xA2, 0x56, 0x1F, 0x15, 0x2F, 0xB8, 0x62, 0xC7, 0xCA, 0xC2}; +// LoRaWAN AppSKey, application session key +static const u1_t PROGMEM APPSKEY[16] = { 0xC4, 0x30, 0xEF, 0x56, 0x4F, 0x6D, 0xA2, 0x56, 0x1F, 0x15, 0x2F, 0xB8, 0x62, 0xC7, 0xCA, 0xC2 }; -// Device Address (MSB) -uint8_t DevAddr[4] = {0x26, 0x02, 0x12, 0xB6}; +// LoRaWAN end-device address (DevAddr) +// See http://thethingsnetwork.org/wiki/AddressSpace +// The library converts the address to network byte order as needed. +#ifndef COMPILE_REGRESSION_TEST +static const u4_t DEVADDR = 0x260212B6; +#else +static const u4_t DEVADDR = 0; +#endif + +// These callbacks are only used in over-the-air activation, so they are +// left empty here (we cannot leave them out completely unless +// DISABLE_JOIN is set in arduino-lmic/project_config/lmic_project_config.h, +// otherwise the linker will complain). +void os_getArtEui (u1_t* buf) { } +void os_getDevEui (u1_t* buf) { } +void os_getDevKey (u1_t* buf) { } + +// payload to send to TTN gateway +//static uint8_t payload[] = "Hello, world!"; -/************************** Example Begins Here ***********************************/ // Data Packet to Send to TTN -unsigned char loraData[Fenceless_CollarResponse_size+1] = {0}; +u1_t loraData[Fenceless_CollarResponse_size+1] = {0}; +static osjob_t sendjob; -// How many times data transfer should occur, in seconds -const unsigned int sendInterval = 3000; +// Schedule TX every this many seconds (might become longer due to duty +// cycle limitations). +const unsigned TX_INTERVAL = 60; + +// Pin mapping for Adafruit Feather M0 LoRa +const lmic_pinmap lmic_pins = { + .nss = 10, + .rxtx = LMIC_UNUSED_PIN, + .rst = 9, + .dio = {2, 3, LMIC_UNUSED_PIN}, + .rxtx_rx_active = 0, + .rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB + .spi_freq = 8000000, +}; + +// init. DHT +//DHT dht(DHTPIN, DHTTYPE); /**************************************************** * Arduino drivers @@ -48,7 +109,6 @@ const unsigned int sendInterval = 3000; * - GPS * - Software Serial ***************************************************/ -TinyLoRa lora = TinyLoRa(2, 10, 9); TinyGPSPlus gps; SoftwareSerial ss(6, 7); @@ -79,6 +139,7 @@ int push_vert(float x, float y) { void clear_verts() { n_poly=0; } + /**************************************************** * Check a pair of coordinates against two lists * of vertices @@ -100,21 +161,6 @@ int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy) int check_bounds(float x, float y) { return pnpoly(n_poly, polyx, polyy, x, y); } -/**************************************************** - * nanopb callback - ***************************************************/ -bool Fenceless_Coordinates_callback(pb_istream_t *stream, const pb_field_iter_t *field, void **arg) { - Serial.println("Called"); - while(stream->bytes_left) { - Fenceless_Coordinate m = Fenceless_Coordinate_init_zero; - if(!pb_decode(stream, Fenceless_Coordinate_fields, &m)) { - return false; - } - push_vert(m.x,m.y); - return true; - } - return false; -} /**************************************************** * Load coordinates from protobuff stream * - currently a maximum of 10 coordinates @@ -123,7 +169,7 @@ bool Fenceless_Coordinates_callback(pb_istream_t *stream, const pb_field_iter_t ***************************************************/ void import_protobuf(uint8_t *protobuffer, uint32_t size) { Fenceless_Coordinates m; - pb_istream_t stream = pb_istream_from_buffer(protobuffer, size); + pb_istream_t stream = pb_istream_from_buffer(protobuffer, size); int status = pb_decode(&stream, Fenceless_Coordinates_fields, &m); if(!status){ Serial.println("Failed to decode"); @@ -150,48 +196,199 @@ void import_protobuf(uint8_t *protobuffer, uint32_t size) { push_vert(m.coord0.x, m.coord0.y); } } -/**************************************************** - * Initialize values - ***************************************************/ -void setup() -{ - // give GPS time to start up - delay(3000); - /**************************************************** - * Configure USART - * - onboard serial to usb - * - software serial connected to GPS module - ***************************************************/ + +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")); + 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; + 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")); + for (int k=0; kPROGRESS_BAR_COUNT*100) { - clear_line(); - loopCounter=0; - - state = VERIFYING_GPS; - } - loopCounter++; + //if(got_data) { + // if(loopCounter%100==0) + // Serial.write('.'); + if(loopCounter>PROGRESS_BAR_COUNT*100) { + // clear_line(); + // loopCounter=0; + // + state = VERIFYING_GPS; } + // loopCounter++; + //} } else if(state == VERIFYING_GPS) { /**************************************************** @@ -284,23 +479,33 @@ void loop() * encode device information into a buffer using * protobuf ***************************************************/ - Fenceless_CollarResponse coord; - coord.loc.x = gps.location.lat(); - coord.loc.y = gps.location.lng(); - coord.oob = check_bounds(coord.loc.x, coord.loc.y); + // Fenceless_CollarResponse coord; + // coord.loc.x = gps.location.lat(); + // coord.loc.y = gps.location.lng(); + // coord.oob = check_bounds(coord.loc.x, coord.loc.y); - pb_ostream_t stream; - stream = pb_ostream_from_buffer(loraData, sizeof(loraData)); - pb_encode(&stream, Fenceless_CollarResponse_fields, &coord); + + // pb_ostream_t stream; + // stream = pb_ostream_from_buffer(loraData, sizeof(loraData)); + // pb_encode(&stream, Fenceless_CollarResponse_fields, &coord); /**************************************************** * send encoded buffer over LoRaWAN ***************************************************/ Serial.println("Sending LoRa Data..."); - lora.sendData(loraData, stream.bytes_written, lora.frameCounter); + do_send(&sendjob); + //lora.sendData(loraData, stream.bytes_written, lora.frameCounter); - Serial.print("Frame Counter: "); - Serial.println(lora.frameCounter); + //lora.sendData(buffer, sizeof(buffer), lora.frameCounter); + + if (LMIC.dataLen) { + Serial.println("Received data back from the gateway: "); + for (int i=0; i= sendInterval) { + if(millis()/1000 - startTime >= TX_INTERVAL) { state = LORA_DONE; } } else if(state == LORA_DONE) { state = VERIFYING_GPS; } + + + + + + + + //os_runloop_once(); }