sends analog data over TTN

Fork of mbed-rtos by mbed official

Committer:
DanL
Date:
Sat Feb 11 17:38:44 2017 +0000
Revision:
124:e39e0bd6eec5
working code for analog temp sensor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DanL 124:e39e0bd6eec5 1 /** mDot_TTN_DL1
DanL 124:e39e0bd6eec5 2 *
DanL 124:e39e0bd6eec5 3 * Demo of use of an analog sensor
DanL 124:e39e0bd6eec5 4 * Based on is a rough demo of mDot+DHT11 on The Things Network.
DanL 124:e39e0bd6eec5 5 *
DanL 124:e39e0bd6eec5 6 * As with the original, this code is not indended as a reference design.
DanL 124:e39e0bd6eec5 7 * In particular, it lacks:
DanL 124:e39e0bd6eec5 8 * (1) power management
DanL 124:e39e0bd6eec5 9 * (2) reasonable transmission period
DanL 124:e39e0bd6eec5 10 * (3) adaptive data rate
DanL 124:e39e0bd6eec5 11 *
DanL 124:e39e0bd6eec5 12 * Uses MultiTech mDot developer board http://www.multitech.com/models/94558010LF
DanL 124:e39e0bd6eec5 13 * Requires a MultiTech MultiConnect Conduit http://www.multitech.com/models/94557203LF
DanL 124:e39e0bd6eec5 14 * http://www.multitech.net/developer/software/lora/conduit-mlinux-convert-to-basic-packet-forwarder/
DanL 124:e39e0bd6eec5 15 * http://forum.thethingsnetwork.org/t/setting-up-multitech-conduit-gateway-for-ttn/216/35
DanL 124:e39e0bd6eec5 16 *
DanL 124:e39e0bd6eec5 17 * To receive and visualize this data,
DanL 124:e39e0bd6eec5 18 * consider using InitialState and the bridge code here:
DanL 124:e39e0bd6eec5 19 * https://github.com/things-nyc/initial-state-example
DanL 124:e39e0bd6eec5 20 */
DanL 124:e39e0bd6eec5 21
DanL 124:e39e0bd6eec5 22 //DL variation -- code compiles before DL work
DanL 124:e39e0bd6eec5 23
DanL 124:e39e0bd6eec5 24 //DL addition
DanL 124:e39e0bd6eec5 25 #define RBUFFER_LEN 8 //number of stored readings
DanL 124:e39e0bd6eec5 26 #define INIT_BYTE 250; //first byte of payload
DanL 124:e39e0bd6eec5 27 #define PAYLOAD_LEN (RBUFFER_LEN + 2)
DanL 124:e39e0bd6eec5 28 //end addition
DanL 124:e39e0bd6eec5 29
DanL 124:e39e0bd6eec5 30
DanL 124:e39e0bd6eec5 31 #include "mbed.h"
DanL 124:e39e0bd6eec5 32 #include "mDot.h"
DanL 124:e39e0bd6eec5 33 #include "MTSLog.h"
DanL 124:e39e0bd6eec5 34 #include "MTSText.h"
DanL 124:e39e0bd6eec5 35 #include <string>
DanL 124:e39e0bd6eec5 36 #include <vector>
DanL 124:e39e0bd6eec5 37
DanL 124:e39e0bd6eec5 38 using namespace mts;
DanL 124:e39e0bd6eec5 39
DanL 124:e39e0bd6eec5 40 #define MIN(a,b) (((a)<(b))?(a):(b))
DanL 124:e39e0bd6eec5 41 #define MAX(a,b) (((a)>(b))?(a):(b))
DanL 124:e39e0bd6eec5 42
DanL 124:e39e0bd6eec5 43
DanL 124:e39e0bd6eec5 44 /** ABP
DanL 124:e39e0bd6eec5 45 * Register your device and update these values: --done dl-mdot-001
DanL 124:e39e0bd6eec5 46 * https://account.thethingsnetwork.org/
DanL 124:e39e0bd6eec5 47 */
DanL 124:e39e0bd6eec5 48 uint8_t AppSKey[16]= { 0x98, 0x29, 0xC2, 0xF2, 0xA9, 0x95, 0xD7, 0x6B, 0x3A, 0xDD, 0x66, 0xBB, 0x5C, 0x1C, 0x65, 0xFD };
DanL 124:e39e0bd6eec5 49 uint8_t NwkSKey[16]= { 0xCB, 0xDC, 0x14, 0xE0, 0x79, 0xF4, 0x83, 0x10, 0x09, 0x99, 0x2D, 0x87, 0xCF, 0x1D, 0x9A, 0xD9 };
DanL 124:e39e0bd6eec5 50 uint8_t NetworkAddr[4]= { 0x26, 0x02, 0x19, 0x70 };
DanL 124:e39e0bd6eec5 51
DanL 124:e39e0bd6eec5 52 //DL additions to globals
DanL 124:e39e0bd6eec5 53 uint8_t readings[RBUFFER_LEN]; // storage for readings
DanL 124:e39e0bd6eec5 54 uint8_t head = 0; //next place to store a reading (better code possible)
DanL 124:e39e0bd6eec5 55 uint8_t payload[PAYLOAD_LEN]; // this will eventually be mydata[]
DanL 124:e39e0bd6eec5 56 //end of additions
DanL 124:e39e0bd6eec5 57
DanL 124:e39e0bd6eec5 58
DanL 124:e39e0bd6eec5 59 // Serial via USB for debugging only DL relocated here from just before main()
DanL 124:e39e0bd6eec5 60 Serial pc(USBTX,USBRX);
DanL 124:e39e0bd6eec5 61
DanL 124:e39e0bd6eec5 62 //DL additions to functions
DanL 124:e39e0bd6eec5 63
DanL 124:e39e0bd6eec5 64 AnalogIn pot_val(PB_1);
DanL 124:e39e0bd6eec5 65
DanL 124:e39e0bd6eec5 66 char readTemp(void)
DanL 124:e39e0bd6eec5 67 {
DanL 124:e39e0bd6eec5 68 unsigned short int reading;
DanL 124:e39e0bd6eec5 69 reading = pot_val.read_u16(); // returns 0 - 0xFFFF in decimal 16 bit read
DanL 124:e39e0bd6eec5 70 reading /= 69; // now in range 0 - 237
DanL 124:e39e0bd6eec5 71 return reading;
DanL 124:e39e0bd6eec5 72 }
DanL 124:e39e0bd6eec5 73
DanL 124:e39e0bd6eec5 74 void dataToBuffer (uint8_t newdata) {
DanL 124:e39e0bd6eec5 75 uint8_t index;
DanL 124:e39e0bd6eec5 76 readings[head] = newdata;
DanL 124:e39e0bd6eec5 77
DanL 124:e39e0bd6eec5 78 //data is now in readings buffer in order received
DanL 124:e39e0bd6eec5 79 //insert data in payload current byte first
DanL 124:e39e0bd6eec5 80 index = head;
DanL 124:e39e0bd6eec5 81 for (uint8_t i = 0 ; i < RBUFFER_LEN ; i++) { // do once for each entry in readings
DanL 124:e39e0bd6eec5 82 payload[i + 1] = readings[index]; //start insert with second byte
DanL 124:e39e0bd6eec5 83 if (index == 0) index = RBUFFER_LEN ;
DanL 124:e39e0bd6eec5 84 index--;
DanL 124:e39e0bd6eec5 85 }
DanL 124:e39e0bd6eec5 86 head++; //set up for next data byte
DanL 124:e39e0bd6eec5 87 if (head > (RBUFFER_LEN - 1)) head = 0;
DanL 124:e39e0bd6eec5 88 //insert battery condition byte here -- payload[PAYLOAD_LEN -1] = batt cond last byte
DanL 124:e39e0bd6eec5 89 payload[PAYLOAD_LEN -1] = 100;
DanL 124:e39e0bd6eec5 90 }
DanL 124:e39e0bd6eec5 91
DanL 124:e39e0bd6eec5 92
DanL 124:e39e0bd6eec5 93
DanL 124:e39e0bd6eec5 94 float decodeTempC(uint8_t c4) { //input is celsius
DanL 124:e39e0bd6eec5 95 float output;
DanL 124:e39e0bd6eec5 96 float input = c4;
DanL 124:e39e0bd6eec5 97 if (c4 <= 240) output = (float(input / 4) - 10); //temperature in range
DanL 124:e39e0bd6eec5 98 if (c4 == 241) {
DanL 124:e39e0bd6eec5 99 pc.printf("below range\n");
DanL 124:e39e0bd6eec5 100 output = 255;
DanL 124:e39e0bd6eec5 101 }
DanL 124:e39e0bd6eec5 102 if (c4 == 242) {
DanL 124:e39e0bd6eec5 103 pc.printf("above range\n");
DanL 124:e39e0bd6eec5 104 output = 255;
DanL 124:e39e0bd6eec5 105 }
DanL 124:e39e0bd6eec5 106 if (c4 == 243) {
DanL 124:e39e0bd6eec5 107 pc.printf("no sensor\n");
DanL 124:e39e0bd6eec5 108 output = 255;
DanL 124:e39e0bd6eec5 109 }
DanL 124:e39e0bd6eec5 110 if (c4 == 244) {
DanL 124:e39e0bd6eec5 111 pc.printf("bad CRC\n");
DanL 124:e39e0bd6eec5 112 output = 255;
DanL 124:e39e0bd6eec5 113 }
DanL 124:e39e0bd6eec5 114 if (c4 >= 245) {
DanL 124:e39e0bd6eec5 115 pc.printf("unknown code\n");
DanL 124:e39e0bd6eec5 116 output = 255;
DanL 124:e39e0bd6eec5 117 }
DanL 124:e39e0bd6eec5 118 return output;
DanL 124:e39e0bd6eec5 119 }
DanL 124:e39e0bd6eec5 120
DanL 124:e39e0bd6eec5 121 float decodeTempF(uint8_t c4) { //input is farenheight
DanL 124:e39e0bd6eec5 122 float output;
DanL 124:e39e0bd6eec5 123 float input = c4;
DanL 124:e39e0bd6eec5 124 if (c4 <= 240) output = (((input / 4) - 10) * 1.8 + 32); //temperature in range
DanL 124:e39e0bd6eec5 125 if (c4 == 241) {
DanL 124:e39e0bd6eec5 126 pc.printf("below range\n");
DanL 124:e39e0bd6eec5 127 output = 255;
DanL 124:e39e0bd6eec5 128 }
DanL 124:e39e0bd6eec5 129 if (c4 == 242) {
DanL 124:e39e0bd6eec5 130 pc.printf("above range\n");
DanL 124:e39e0bd6eec5 131 output = 255;
DanL 124:e39e0bd6eec5 132 }
DanL 124:e39e0bd6eec5 133 if (c4 == 243) {
DanL 124:e39e0bd6eec5 134 pc.printf("no sensor\n");
DanL 124:e39e0bd6eec5 135 output = 255;
DanL 124:e39e0bd6eec5 136 }
DanL 124:e39e0bd6eec5 137 if (c4 == 244) {
DanL 124:e39e0bd6eec5 138 pc.printf("bad CRC\n");
DanL 124:e39e0bd6eec5 139 output = 255;
DanL 124:e39e0bd6eec5 140 }
DanL 124:e39e0bd6eec5 141 if (c4 >= 245) {
DanL 124:e39e0bd6eec5 142 pc.printf("unknown code\n");
DanL 124:e39e0bd6eec5 143 output = 255;
DanL 124:e39e0bd6eec5 144 }
DanL 124:e39e0bd6eec5 145 return output;
DanL 124:e39e0bd6eec5 146 }
DanL 124:e39e0bd6eec5 147
DanL 124:e39e0bd6eec5 148 //end of DL additions to functions
DanL 124:e39e0bd6eec5 149
DanL 124:e39e0bd6eec5 150
DanL 124:e39e0bd6eec5 151 // Some defines for the LoRa configuration
DanL 124:e39e0bd6eec5 152 #define LORA_SF mDot::SF_7
DanL 124:e39e0bd6eec5 153 #define LORA_ACK 0
DanL 124:e39e0bd6eec5 154 #define LORA_TXPOWER 20
DanL 124:e39e0bd6eec5 155 static uint8_t config_frequency_sub_band = 2;
DanL 124:e39e0bd6eec5 156
DanL 124:e39e0bd6eec5 157 // functions for ensuring network endianness (little-endian)
DanL 124:e39e0bd6eec5 158 uint16_t hton16(const uint16_t x)
DanL 124:e39e0bd6eec5 159 {
DanL 124:e39e0bd6eec5 160 uint16_t t = x;
DanL 124:e39e0bd6eec5 161 uint8_t * a = (uint8_t*)&t;
DanL 124:e39e0bd6eec5 162 a[0] = x>>(8*1);
DanL 124:e39e0bd6eec5 163 a[1] = x>>(8*0);
DanL 124:e39e0bd6eec5 164 return t;
DanL 124:e39e0bd6eec5 165 }
DanL 124:e39e0bd6eec5 166 void hton16(uint16_t * x)
DanL 124:e39e0bd6eec5 167 {
DanL 124:e39e0bd6eec5 168 *x = hton16(*x);
DanL 124:e39e0bd6eec5 169 }
DanL 124:e39e0bd6eec5 170
DanL 124:e39e0bd6eec5 171
DanL 124:e39e0bd6eec5 172 /*
DanL 124:e39e0bd6eec5 173 // build a transmit buffer (from https://raw.githubusercontent.com/mcci-catena/Catena4410-Sketches/master/catena4410_sensor1/catena4410_sensor1.ino)
DanL 124:e39e0bd6eec5 174 class TxBuffer_t
DanL 124:e39e0bd6eec5 175 {
DanL 124:e39e0bd6eec5 176 public:
DanL 124:e39e0bd6eec5 177 uint8_t buf[32]; // this sets the largest buffer size
DanL 124:e39e0bd6eec5 178 uint8_t *p;
DanL 124:e39e0bd6eec5 179
DanL 124:e39e0bd6eec5 180 TxBuffer_t() : p(buf) {};
DanL 124:e39e0bd6eec5 181 void begin()
DanL 124:e39e0bd6eec5 182 {
DanL 124:e39e0bd6eec5 183 p = buf;
DanL 124:e39e0bd6eec5 184 }
DanL 124:e39e0bd6eec5 185 void put(uint8_t c)
DanL 124:e39e0bd6eec5 186 {
DanL 124:e39e0bd6eec5 187 if (p < buf + sizeof(buf))
DanL 124:e39e0bd6eec5 188 *p++ = c;
DanL 124:e39e0bd6eec5 189 }
DanL 124:e39e0bd6eec5 190 void put1u(int32_t v)
DanL 124:e39e0bd6eec5 191 {
DanL 124:e39e0bd6eec5 192 if (v > 0xFF)
DanL 124:e39e0bd6eec5 193 v = 0xFF;
DanL 124:e39e0bd6eec5 194 else if (v < 0)
DanL 124:e39e0bd6eec5 195 v = 0;
DanL 124:e39e0bd6eec5 196 put((uint8_t) v);
DanL 124:e39e0bd6eec5 197 }
DanL 124:e39e0bd6eec5 198 void put2(uint32_t v)
DanL 124:e39e0bd6eec5 199 {
DanL 124:e39e0bd6eec5 200 if (v > 0xFFFF)
DanL 124:e39e0bd6eec5 201 v = 0xFFFF;
DanL 124:e39e0bd6eec5 202
DanL 124:e39e0bd6eec5 203 put((uint8_t) (v >> 8));
DanL 124:e39e0bd6eec5 204 put((uint8_t) v);
DanL 124:e39e0bd6eec5 205 }
DanL 124:e39e0bd6eec5 206 void put2(int32_t v)
DanL 124:e39e0bd6eec5 207 {
DanL 124:e39e0bd6eec5 208 if (v < -0x8000)
DanL 124:e39e0bd6eec5 209 v = -0x8000;
DanL 124:e39e0bd6eec5 210 else if (v > 0x7FFF)
DanL 124:e39e0bd6eec5 211 v = 0x7FFF;
DanL 124:e39e0bd6eec5 212
DanL 124:e39e0bd6eec5 213 put2((uint32_t) v);
DanL 124:e39e0bd6eec5 214 }
DanL 124:e39e0bd6eec5 215 void put3(uint32_t v)
DanL 124:e39e0bd6eec5 216 {
DanL 124:e39e0bd6eec5 217 if (v > 0xFFFFFF)
DanL 124:e39e0bd6eec5 218 v = 0xFFFFFF;
DanL 124:e39e0bd6eec5 219
DanL 124:e39e0bd6eec5 220 put((uint8_t) (v >> 16));
DanL 124:e39e0bd6eec5 221 put((uint8_t) (v >> 8));
DanL 124:e39e0bd6eec5 222 put((uint8_t) v);
DanL 124:e39e0bd6eec5 223 }
DanL 124:e39e0bd6eec5 224 void put2u(int32_t v)
DanL 124:e39e0bd6eec5 225 {
DanL 124:e39e0bd6eec5 226 if (v < 0)
DanL 124:e39e0bd6eec5 227 v = 0;
DanL 124:e39e0bd6eec5 228 else if (v > 0xFFFF)
DanL 124:e39e0bd6eec5 229 v = 0xFFFF;
DanL 124:e39e0bd6eec5 230 put2((uint32_t) v);
DanL 124:e39e0bd6eec5 231 }
DanL 124:e39e0bd6eec5 232 void put3(int32_t v)
DanL 124:e39e0bd6eec5 233 {
DanL 124:e39e0bd6eec5 234 if (v < -0x800000)
DanL 124:e39e0bd6eec5 235 v = -0x800000;
DanL 124:e39e0bd6eec5 236 else if (v > 0x7FFFFF)
DanL 124:e39e0bd6eec5 237 v = 0x7FFFFF;
DanL 124:e39e0bd6eec5 238 put3((uint32_t) v);
DanL 124:e39e0bd6eec5 239 }
DanL 124:e39e0bd6eec5 240 uint8_t *getp(void)
DanL 124:e39e0bd6eec5 241 {
DanL 124:e39e0bd6eec5 242 return p;
DanL 124:e39e0bd6eec5 243 }
DanL 124:e39e0bd6eec5 244 size_t getn(void)
DanL 124:e39e0bd6eec5 245 {
DanL 124:e39e0bd6eec5 246 return p - buf;
DanL 124:e39e0bd6eec5 247 }
DanL 124:e39e0bd6eec5 248 uint8_t *getbase(void)
DanL 124:e39e0bd6eec5 249 {
DanL 124:e39e0bd6eec5 250 return buf;
DanL 124:e39e0bd6eec5 251 }
DanL 124:e39e0bd6eec5 252 void put2sf(float v)
DanL 124:e39e0bd6eec5 253 {
DanL 124:e39e0bd6eec5 254 int32_t iv;
DanL 124:e39e0bd6eec5 255
DanL 124:e39e0bd6eec5 256 if (v > 32766.5f)
DanL 124:e39e0bd6eec5 257 iv = 0x7fff;
DanL 124:e39e0bd6eec5 258 else if (v < -32767.5f)
DanL 124:e39e0bd6eec5 259 iv = -0x8000;
DanL 124:e39e0bd6eec5 260 else
DanL 124:e39e0bd6eec5 261 iv = (int32_t)(v + 0.5f);
DanL 124:e39e0bd6eec5 262
DanL 124:e39e0bd6eec5 263 put2(iv);
DanL 124:e39e0bd6eec5 264 }
DanL 124:e39e0bd6eec5 265 void put2uf(float v)
DanL 124:e39e0bd6eec5 266 {
DanL 124:e39e0bd6eec5 267 uint32_t iv;
DanL 124:e39e0bd6eec5 268
DanL 124:e39e0bd6eec5 269 if (v > 65535.5f)
DanL 124:e39e0bd6eec5 270 iv = 0xffff;
DanL 124:e39e0bd6eec5 271 else if (v < 0.5f)
DanL 124:e39e0bd6eec5 272 iv = 0;
DanL 124:e39e0bd6eec5 273 else
DanL 124:e39e0bd6eec5 274 iv = (uint32_t)(v + 0.5f);
DanL 124:e39e0bd6eec5 275
DanL 124:e39e0bd6eec5 276 put2(iv);
DanL 124:e39e0bd6eec5 277 }
DanL 124:e39e0bd6eec5 278 void put1uf(float v)
DanL 124:e39e0bd6eec5 279 {
DanL 124:e39e0bd6eec5 280 uint8_t c;
DanL 124:e39e0bd6eec5 281
DanL 124:e39e0bd6eec5 282 if (v > 254.5)
DanL 124:e39e0bd6eec5 283 c = 0xFF;
DanL 124:e39e0bd6eec5 284 else if (v < 0.5)
DanL 124:e39e0bd6eec5 285 c = 0;
DanL 124:e39e0bd6eec5 286 else
DanL 124:e39e0bd6eec5 287 c = (uint8_t) v;
DanL 124:e39e0bd6eec5 288
DanL 124:e39e0bd6eec5 289 put(c);
DanL 124:e39e0bd6eec5 290 }
DanL 124:e39e0bd6eec5 291 void putT(float T)
DanL 124:e39e0bd6eec5 292 {
DanL 124:e39e0bd6eec5 293 put2sf(T * 256.0f + 0.5f);
DanL 124:e39e0bd6eec5 294 }
DanL 124:e39e0bd6eec5 295 void putRH(float RH)
DanL 124:e39e0bd6eec5 296 {
DanL 124:e39e0bd6eec5 297 put1uf((RH / 0.390625f) + 0.5f);
DanL 124:e39e0bd6eec5 298 }
DanL 124:e39e0bd6eec5 299 void putV(float V)
DanL 124:e39e0bd6eec5 300 {
DanL 124:e39e0bd6eec5 301 put2sf(V * 4096.0f + 0.5f);
DanL 124:e39e0bd6eec5 302 }
DanL 124:e39e0bd6eec5 303 void putP(float P)
DanL 124:e39e0bd6eec5 304 {
DanL 124:e39e0bd6eec5 305 put2uf(P / 4.0f + 0.5f);
DanL 124:e39e0bd6eec5 306 }
DanL 124:e39e0bd6eec5 307 void putLux(float Lux)
DanL 124:e39e0bd6eec5 308 {
DanL 124:e39e0bd6eec5 309 put2uf(Lux);
DanL 124:e39e0bd6eec5 310 }
DanL 124:e39e0bd6eec5 311 }; */
DanL 124:e39e0bd6eec5 312
DanL 124:e39e0bd6eec5 313 /* the magic byte at the front of the buffer */
DanL 124:e39e0bd6eec5 314 enum {
DanL 124:e39e0bd6eec5 315 FormatSensor1 = 0x11,
DanL 124:e39e0bd6eec5 316 };
DanL 124:e39e0bd6eec5 317
DanL 124:e39e0bd6eec5 318 /* the flags for the second byte of the buffer */
DanL 124:e39e0bd6eec5 319 enum {
DanL 124:e39e0bd6eec5 320 FlagVbat = 1 << 0,
DanL 124:e39e0bd6eec5 321 FlagVcc = 1 << 1,
DanL 124:e39e0bd6eec5 322 FlagTPH = 1 << 2,
DanL 124:e39e0bd6eec5 323 FlagLux = 1 << 3,
DanL 124:e39e0bd6eec5 324 FlagWater = 1 << 4,
DanL 124:e39e0bd6eec5 325 FlagSoilTH = 1 << 5,
DanL 124:e39e0bd6eec5 326 };
DanL 124:e39e0bd6eec5 327
DanL 124:e39e0bd6eec5 328
DanL 124:e39e0bd6eec5 329 // Temperature sensor object
DanL 124:e39e0bd6eec5 330 //#define DHT_PIN PB_1
DanL 124:e39e0bd6eec5 331 //DHT11 dht(DHT_PIN);
DanL 124:e39e0bd6eec5 332
DanL 124:e39e0bd6eec5 333
DanL 124:e39e0bd6eec5 334 int main()
DanL 124:e39e0bd6eec5 335 {
DanL 124:e39e0bd6eec5 336 // TxBuffer_t b;
DanL 124:e39e0bd6eec5 337
DanL 124:e39e0bd6eec5 338 int32_t ret;
DanL 124:e39e0bd6eec5 339 mDot* dot;
DanL 124:e39e0bd6eec5 340 std::vector<uint8_t> send_data;
DanL 124:e39e0bd6eec5 341 std::vector<uint8_t> recv_data;
DanL 124:e39e0bd6eec5 342 std::vector<uint8_t> nwkSKey;
DanL 124:e39e0bd6eec5 343 std::vector<uint8_t> appSKey;
DanL 124:e39e0bd6eec5 344 std::vector<uint8_t> nodeAddr;
DanL 124:e39e0bd6eec5 345 std::vector<uint8_t> networkAddr;
DanL 124:e39e0bd6eec5 346
DanL 124:e39e0bd6eec5 347 // float temperature = 0.0;
DanL 124:e39e0bd6eec5 348 uint8_t currentTemp; //DP
DanL 124:e39e0bd6eec5 349 payload[0] = INIT_BYTE; // DL set up initial byte
DanL 124:e39e0bd6eec5 350
DanL 124:e39e0bd6eec5 351 pc.baud(115200);
DanL 124:e39e0bd6eec5 352 pc.printf("TTN mDot LoRa Temperature & Humidity Sensor\n\r");
DanL 124:e39e0bd6eec5 353
DanL 124:e39e0bd6eec5 354 // get a mDot handle
DanL 124:e39e0bd6eec5 355 dot = mDot::getInstance();
DanL 124:e39e0bd6eec5 356
DanL 124:e39e0bd6eec5 357 // dot->setLogLevel(MTSLog::WARNING_LEVEL);
DanL 124:e39e0bd6eec5 358 dot->setLogLevel(MTSLog::TRACE_LEVEL);
DanL 124:e39e0bd6eec5 359
DanL 124:e39e0bd6eec5 360 logInfo("Checking Config");
DanL 124:e39e0bd6eec5 361
DanL 124:e39e0bd6eec5 362 // Test if we've already saved the config
DanL 124:e39e0bd6eec5 363 std::string configNetworkName = dot->getNetworkName();
DanL 124:e39e0bd6eec5 364
DanL 124:e39e0bd6eec5 365 uint8_t *it = NwkSKey;
DanL 124:e39e0bd6eec5 366 for (uint8_t i = 0; i<16; i++)
DanL 124:e39e0bd6eec5 367 nwkSKey.push_back((uint8_t) *it++);
DanL 124:e39e0bd6eec5 368
DanL 124:e39e0bd6eec5 369 it = AppSKey;
DanL 124:e39e0bd6eec5 370 for (uint8_t i = 0; i<16; i++)
DanL 124:e39e0bd6eec5 371 appSKey.push_back((uint8_t) *it++);
DanL 124:e39e0bd6eec5 372
DanL 124:e39e0bd6eec5 373 it = NetworkAddr;
DanL 124:e39e0bd6eec5 374 for (uint8_t i = 0; i<4; i++)
DanL 124:e39e0bd6eec5 375 networkAddr.push_back((uint8_t) *it++);
DanL 124:e39e0bd6eec5 376
DanL 124:e39e0bd6eec5 377 logInfo("Resetting Config");
DanL 124:e39e0bd6eec5 378 // reset to default config so we know what state we're in
DanL 124:e39e0bd6eec5 379 dot->resetConfig();
DanL 124:e39e0bd6eec5 380
DanL 124:e39e0bd6eec5 381 // Set byte order - AEP less than 1.0.30
DanL 124:e39e0bd6eec5 382 // dot->setJoinByteOrder(mDot::LSB);
DanL 124:e39e0bd6eec5 383 dot->setJoinByteOrder(mDot::MSB); // This is default for > 1.0.30 Conduit
DanL 124:e39e0bd6eec5 384
DanL 124:e39e0bd6eec5 385
DanL 124:e39e0bd6eec5 386
DanL 124:e39e0bd6eec5 387 logInfo("Set TxPower");
DanL 124:e39e0bd6eec5 388 if((ret = dot->setTxPower( LORA_TXPOWER )) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 389 logError("Failed to set Tx Power %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 390 }
DanL 124:e39e0bd6eec5 391
DanL 124:e39e0bd6eec5 392 logInfo("Set Public mode");
DanL 124:e39e0bd6eec5 393 if((ret = dot->setPublicNetwork(true)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 394 logError("failed to set Public Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 395 }
DanL 124:e39e0bd6eec5 396
DanL 124:e39e0bd6eec5 397 logInfo("Set MANUAL Join mode");
DanL 124:e39e0bd6eec5 398 if((ret = dot->setJoinMode(mDot::MANUAL)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 399 logError("Failed to set MANUAL Join Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 400 }
DanL 124:e39e0bd6eec5 401
DanL 124:e39e0bd6eec5 402 logInfo("Set Ack");
DanL 124:e39e0bd6eec5 403 // 1 retries on Ack, 0 to disable
DanL 124:e39e0bd6eec5 404 if((ret = dot->setAck( LORA_ACK)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 405 logError("Failed to set Ack %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 406 }
DanL 124:e39e0bd6eec5 407
DanL 124:e39e0bd6eec5 408 //Not applicable for 868MHz in EU
DanL 124:e39e0bd6eec5 409 if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 410 logError("failed to set frequency sub band", ret);
DanL 124:e39e0bd6eec5 411 }
DanL 124:e39e0bd6eec5 412
DanL 124:e39e0bd6eec5 413 logInfo("Set Network Address");
DanL 124:e39e0bd6eec5 414 if ((ret = dot->setNetworkAddress(networkAddr)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 415 logError("Failed to set Network Address %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 416 }
DanL 124:e39e0bd6eec5 417
DanL 124:e39e0bd6eec5 418 logInfo("Set Data Session Key");
DanL 124:e39e0bd6eec5 419 if ((ret = dot->setDataSessionKey(appSKey)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 420 logError("Failed to set Data Session Key %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 421 }
DanL 124:e39e0bd6eec5 422
DanL 124:e39e0bd6eec5 423 logInfo("Set Network Session Key");
DanL 124:e39e0bd6eec5 424 if ((ret = dot->setNetworkSessionKey(nwkSKey)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 425 logError("Failed to set Network Session Key %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 426 }
DanL 124:e39e0bd6eec5 427
DanL 124:e39e0bd6eec5 428 logInfo("Saving Config");
DanL 124:e39e0bd6eec5 429 // Save config
DanL 124:e39e0bd6eec5 430 if (! dot->saveConfig()) {
DanL 124:e39e0bd6eec5 431 logError("failed to save configuration");
DanL 124:e39e0bd6eec5 432 }
DanL 124:e39e0bd6eec5 433
DanL 124:e39e0bd6eec5 434 // Display what is set
DanL 124:e39e0bd6eec5 435 std::vector<uint8_t> tmp = dot->getNetworkSessionKey();
DanL 124:e39e0bd6eec5 436 pc.printf("Network Session Key: ");
DanL 124:e39e0bd6eec5 437 pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
DanL 124:e39e0bd6eec5 438
DanL 124:e39e0bd6eec5 439 tmp = dot->getDataSessionKey();
DanL 124:e39e0bd6eec5 440 pc.printf("Data Session Key: ");
DanL 124:e39e0bd6eec5 441 pc.printf("%s\r\n", mts::Text::bin2hexString(tmp, " ").c_str());
DanL 124:e39e0bd6eec5 442
DanL 124:e39e0bd6eec5 443 pc.printf("Device ID ");
DanL 124:e39e0bd6eec5 444 std::vector<uint8_t> deviceId;
DanL 124:e39e0bd6eec5 445 deviceId = dot->getDeviceId();
DanL 124:e39e0bd6eec5 446 for (std::vector<uint8_t>::iterator it = deviceId.begin() ; it != deviceId.end(); ++it)
DanL 124:e39e0bd6eec5 447 pc.printf("%2.2x",*it );
DanL 124:e39e0bd6eec5 448 pc.printf("\r\n");
DanL 124:e39e0bd6eec5 449
DanL 124:e39e0bd6eec5 450 std::vector<uint8_t> netAddress;
DanL 124:e39e0bd6eec5 451
DanL 124:e39e0bd6eec5 452 pc.printf("Network Address ");
DanL 124:e39e0bd6eec5 453 netAddress = dot->getNetworkAddress();
DanL 124:e39e0bd6eec5 454 for (std::vector<uint8_t>::iterator it = netAddress.begin() ; it != netAddress.end(); ++it)
DanL 124:e39e0bd6eec5 455 pc.printf("%2.2x",*it );
DanL 124:e39e0bd6eec5 456
DanL 124:e39e0bd6eec5 457 pc.printf("\r\n");
DanL 124:e39e0bd6eec5 458
DanL 124:e39e0bd6eec5 459 // Display LoRa parameters
DanL 124:e39e0bd6eec5 460 // Display label and values in different colours, show pretty values not numeric values where applicable
DanL 124:e39e0bd6eec5 461 pc.printf("Public Network: %s\r\n", (char*)(dot->getPublicNetwork() ? "Yes" : "No") );
DanL 124:e39e0bd6eec5 462 pc.printf("Frequency: %s\r\n", (char*)mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str() );
DanL 124:e39e0bd6eec5 463 pc.printf("Sub Band: %s\r\n", (char*)mDot::FrequencySubBandStr(dot->getFrequencySubBand()).c_str() );
DanL 124:e39e0bd6eec5 464 pc.printf("Join Mode: %s\r\n", (char*)mDot::JoinModeStr(dot->getJoinMode()).c_str() );
DanL 124:e39e0bd6eec5 465 pc.printf("Join Retries: %d\r\n", dot->getJoinRetries() );
DanL 124:e39e0bd6eec5 466 pc.printf("Join Byte Order: %s\r\n", (char*)(dot->getJoinByteOrder() == 0 ? "LSB" : "MSB") );
DanL 124:e39e0bd6eec5 467 pc.printf("Link Check Count: %d\r\n", dot->getLinkCheckCount() );
DanL 124:e39e0bd6eec5 468 pc.printf("Link Check Thold: %d\r\n", dot->getLinkCheckThreshold() );
DanL 124:e39e0bd6eec5 469 pc.printf("Tx Data Rate: %s\r\n", (char*)mDot::DataRateStr(dot->getTxDataRate()).c_str() );
DanL 124:e39e0bd6eec5 470 pc.printf("Tx Power: %d\r\n", dot->getTxPower() );
DanL 124:e39e0bd6eec5 471 pc.printf("TxWait: %s, ", (dot->getTxWait() ? "Y" : "N" ));
DanL 124:e39e0bd6eec5 472 pc.printf("CRC: %s, ", (dot->getCrc() ? "Y" : "N") );
DanL 124:e39e0bd6eec5 473 pc.printf("Ack: %s\r\n", (dot->getAck() ? "Y" : "N") );
DanL 124:e39e0bd6eec5 474
DanL 124:e39e0bd6eec5 475 logInfo("Joining Network");
DanL 124:e39e0bd6eec5 476
DanL 124:e39e0bd6eec5 477 while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 478 logError("failed to join network [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 479 wait_ms(dot->getNextTxMs() + 1);
DanL 124:e39e0bd6eec5 480 }
DanL 124:e39e0bd6eec5 481
DanL 124:e39e0bd6eec5 482 logInfo("Joined Network");
DanL 124:e39e0bd6eec5 483
DanL 124:e39e0bd6eec5 484 // char dataBuf[50];
DanL 124:e39e0bd6eec5 485 uint16_t seq = 0;
DanL 124:e39e0bd6eec5 486 char * sf_str;
DanL 124:e39e0bd6eec5 487 while( 1 ) {
DanL 124:e39e0bd6eec5 488
DanL 124:e39e0bd6eec5 489 /* cycle through spreading factors */
DanL 124:e39e0bd6eec5 490 uint8_t sf;
DanL 124:e39e0bd6eec5 491 switch (seq % 4) {
DanL 124:e39e0bd6eec5 492 case 0:
DanL 124:e39e0bd6eec5 493 sf = mDot::SF_7;
DanL 124:e39e0bd6eec5 494 sf_str = "SF7";
DanL 124:e39e0bd6eec5 495 break;
DanL 124:e39e0bd6eec5 496 case 1:
DanL 124:e39e0bd6eec5 497 sf = mDot::SF_8;
DanL 124:e39e0bd6eec5 498 sf_str = "SF8";
DanL 124:e39e0bd6eec5 499 break;
DanL 124:e39e0bd6eec5 500 case 2:
DanL 124:e39e0bd6eec5 501 sf = mDot::SF_9;
DanL 124:e39e0bd6eec5 502 sf_str = "SF9";
DanL 124:e39e0bd6eec5 503 break;
DanL 124:e39e0bd6eec5 504 case 3:
DanL 124:e39e0bd6eec5 505 sf = mDot::SF_10;
DanL 124:e39e0bd6eec5 506 sf_str = "SF10";
DanL 124:e39e0bd6eec5 507 break;
DanL 124:e39e0bd6eec5 508 }
DanL 124:e39e0bd6eec5 509 // Set Spreading Factor, higher is lower data rate, smaller packets but longer range
DanL 124:e39e0bd6eec5 510 // Lower is higher data rate, larger packets and shorter range.
DanL 124:e39e0bd6eec5 511 logInfo("Set SF: %s",sf_str);
DanL 124:e39e0bd6eec5 512 if((ret = dot->setTxDataRate( sf )) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 513 logError("Failed to set SF %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 514 }
DanL 124:e39e0bd6eec5 515
DanL 124:e39e0bd6eec5 516 /* set default data values */
DanL 124:e39e0bd6eec5 517 // int temp = 0;
DanL 124:e39e0bd6eec5 518 // int humid = -1;
DanL 124:e39e0bd6eec5 519
DanL 124:e39e0bd6eec5 520 /* read from sensor */
DanL 124:e39e0bd6eec5 521 /* int r = dht.readData();
DanL 124:e39e0bd6eec5 522 switch (r) {
DanL 124:e39e0bd6eec5 523 case DHT11::OK:
DanL 124:e39e0bd6eec5 524 {
DanL 124:e39e0bd6eec5 525 temp = dht.readTemperature();
DanL 124:e39e0bd6eec5 526 humid = dht.readHumidity();
DanL 124:e39e0bd6eec5 527 pc.printf("[DHT] T %d degC H %d %%\r\n",temp,humid);
DanL 124:e39e0bd6eec5 528 break;
DanL 124:e39e0bd6eec5 529 }
DanL 124:e39e0bd6eec5 530 default:
DanL 124:e39e0bd6eec5 531 {
DanL 124:e39e0bd6eec5 532 pc.printf("[DHT] ERROR %d\r\n",r);
DanL 124:e39e0bd6eec5 533 break;
DanL 124:e39e0bd6eec5 534 }
DanL 124:e39e0bd6eec5 535 }; */
DanL 124:e39e0bd6eec5 536
DanL 124:e39e0bd6eec5 537 /* build packet */
DanL 124:e39e0bd6eec5 538 /* b.begin();
DanL 124:e39e0bd6eec5 539 uint8_t flag = 0;
DanL 124:e39e0bd6eec5 540 b.put(FormatSensor1);
DanL 124:e39e0bd6eec5 541 uint8_t * const pFlag = b.getp(); // save pointer to flag location
DanL 124:e39e0bd6eec5 542 b.put(0x00); // placeholder for flags
DanL 124:e39e0bd6eec5 543 */
DanL 124:e39e0bd6eec5 544 /* // TODO: read battery voltage
DanL 124:e39e0bd6eec5 545 b.putV(13.8);
DanL 124:e39e0bd6eec5 546 flag |= FlagVbat;
DanL 124:e39e0bd6eec5 547
DanL 124:e39e0bd6eec5 548 // TODO: read from Bme280 sensor:
DanL 124:e39e0bd6eec5 549 b.putT(27.0); // air temp
DanL 124:e39e0bd6eec5 550 b.putP(1010.0); // air pressure
DanL 124:e39e0bd6eec5 551 b.putRH(66.0); // air humidity
DanL 124:e39e0bd6eec5 552 flag |= FlagTPH;
DanL 124:e39e0bd6eec5 553
DanL 124:e39e0bd6eec5 554 // TODO: read from light sensor
DanL 124:e39e0bd6eec5 555 b.putLux(1234); // ambient light
DanL 124:e39e0bd6eec5 556 flag |= FlagLux;
DanL 124:e39e0bd6eec5 557
DanL 124:e39e0bd6eec5 558 // TODO: read water temperature
DanL 124:e39e0bd6eec5 559 b.putT(22.0); // water temperature
DanL 124:e39e0bd6eec5 560 flag |= FlagWater;
DanL 124:e39e0bd6eec5 561
DanL 124:e39e0bd6eec5 562 // TODO: read soil sensor
DanL 124:e39e0bd6eec5 563 b.putT(25.2); // soil temperature
DanL 124:e39e0bd6eec5 564 b.putRH(82.0); // soil humidity
DanL 124:e39e0bd6eec5 565 flag |= FlagSoilTH;
DanL 124:e39e0bd6eec5 566
DanL 124:e39e0bd6eec5 567 // write flag byte
DanL 124:e39e0bd6eec5 568 *pFlag = flag;
DanL 124:e39e0bd6eec5 569
DanL 124:e39e0bd6eec5 570 */
DanL 124:e39e0bd6eec5 571 //DL stuff added
DanL 124:e39e0bd6eec5 572
DanL 124:e39e0bd6eec5 573 //DL additions
DanL 124:e39e0bd6eec5 574
DanL 124:e39e0bd6eec5 575 currentTemp = readTemp();
DanL 124:e39e0bd6eec5 576 pc.printf(" %.2f \n", decodeTempC(currentTemp)); //for debugging- returns degrees celsius as a float
DanL 124:e39e0bd6eec5 577 pc.printf(" %.2f \n", decodeTempF(currentTemp)); //for debugging- returns degrees farenheight as a float
DanL 124:e39e0bd6eec5 578 //put recent readings into a buffer with most recent data first
DanL 124:e39e0bd6eec5 579 dataToBuffer (currentTemp); //adds data to buffer and payload
DanL 124:e39e0bd6eec5 580
DanL 124:e39e0bd6eec5 581 //print payload for debugging
DanL 124:e39e0bd6eec5 582 pc.printf(" %d \n", currentTemp);
DanL 124:e39e0bd6eec5 583 pc.printf("Payload ");
DanL 124:e39e0bd6eec5 584 for (uint8_t i = 0 ; i < PAYLOAD_LEN ; i++){
DanL 124:e39e0bd6eec5 585 pc.printf("%d ",payload[i]);
DanL 124:e39e0bd6eec5 586 pc.printf(" ");
DanL 124:e39e0bd6eec5 587 }
DanL 124:e39e0bd6eec5 588 pc.printf("\n");
DanL 124:e39e0bd6eec5 589 //end of payload printout
DanL 124:e39e0bd6eec5 590
DanL 124:e39e0bd6eec5 591 //wait_ms(1500);
DanL 124:e39e0bd6eec5 592
DanL 124:e39e0bd6eec5 593 //end of DL adds
DanL 124:e39e0bd6eec5 594
DanL 124:e39e0bd6eec5 595
DanL 124:e39e0bd6eec5 596 /* load vector */
DanL 124:e39e0bd6eec5 597 /* send_data.clear();
DanL 124:e39e0bd6eec5 598 / uint8_t c;
DanL 124:e39e0bd6eec5 599 int n = b.getn();
DanL 124:e39e0bd6eec5 600 for( int i=0; i< n; i++ ) {
DanL 124:e39e0bd6eec5 601 c = b.buf[i];
DanL 124:e39e0bd6eec5 602 send_data.push_back( c );
DanL 124:e39e0bd6eec5 603 }*/
DanL 124:e39e0bd6eec5 604
DanL 124:e39e0bd6eec5 605
DanL 124:e39e0bd6eec5 606 //DL Load Veector from HS Payload
DanL 124:e39e0bd6eec5 607 send_data.clear();
DanL 124:e39e0bd6eec5 608 uint8_t c;
DanL 124:e39e0bd6eec5 609 for( int i=0; i< PAYLOAD_LEN ; i++ ) {
DanL 124:e39e0bd6eec5 610 c = payload[i];
DanL 124:e39e0bd6eec5 611 send_data.push_back( c );
DanL 124:e39e0bd6eec5 612 }
DanL 124:e39e0bd6eec5 613
DanL 124:e39e0bd6eec5 614 /* send packet */
DanL 124:e39e0bd6eec5 615 if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
DanL 124:e39e0bd6eec5 616 logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
DanL 124:e39e0bd6eec5 617 } else {
DanL 124:e39e0bd6eec5 618 logInfo("data len: %d, send data: %s", PAYLOAD_LEN, Text::bin2hexString(send_data).c_str()); //PAYLOAD_LEN constant instead of b length variable
DanL 124:e39e0bd6eec5 619 }
DanL 124:e39e0bd6eec5 620
DanL 124:e39e0bd6eec5 621 /* sleep */
DanL 124:e39e0bd6eec5 622 uint32_t sleep_time = MAX((dot->getNextTxMs() / 1000), 10 /* use 6000 for 10min */);
DanL 124:e39e0bd6eec5 623 logInfo("going to sleep for %d seconds", sleep_time);
DanL 124:e39e0bd6eec5 624 wait_ms(10*1000);
DanL 124:e39e0bd6eec5 625
DanL 124:e39e0bd6eec5 626 seq++;
DanL 124:e39e0bd6eec5 627 }
DanL 124:e39e0bd6eec5 628
DanL 124:e39e0bd6eec5 629 return 0;
DanL 124:e39e0bd6eec5 630 }