_sensor.ino 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. // sensor.ino; 1-channel LoRa Gateway for ESP8266
  2. // Copyright (c) 2016, 2017, 2018, 2019 Maarten Westenberg
  3. // Verison 6.1.3
  4. // Date: 2019-11-20
  5. //
  6. // All rights reserved. This program and the accompanying materials
  7. // are made available under the terms of the MIT License
  8. // which accompanies this distribution, and is available at
  9. // https://opensource.org/licenses/mit-license.php
  10. //
  11. // NO WARRANTY OF ANY KIND IS PROVIDED
  12. //
  13. // Author: Maarten Westenberg (mw12554@hotmail.com)
  14. //
  15. // This file contains code for using the single channel gateway also as a sensor node.
  16. // Please specify the DevAddr and the AppSKey below (and on your LoRa backend).
  17. // Also you will have to choose what sensors to forward to your application.
  18. //
  19. // Note: disable sensors not used in configGway.h
  20. // - The GPS is included on TTGO T-Beam ESP32 boards by default.
  21. // - The battery sensor works by connecting the VCC pin to A0 analog port
  22. // ============================================================================
  23. #if GATEWAYNODE==1
  24. #include "LoRaCode.h"
  25. unsigned char DevAddr[4] = _DEVADDR ; // see configGway.h
  26. // Only used by GPS sensor code
  27. #if _GPS==1
  28. // ----------------------------------------------------------------------------
  29. // Smartdelay is a function to delay processing but in the loop get info
  30. // from the GPS device
  31. // ----------------------------------------------------------------------------
  32. static void smartDelay(unsigned long ms)
  33. {
  34. unsigned long start = millis();
  35. do
  36. {
  37. while (Serial1.available())
  38. gps.encode(Serial1.read());
  39. } while (millis() - start < ms);
  40. }
  41. #endif //_GPS
  42. // ----------------------------------------------------------------------------
  43. // LoRaSensors() is a function that puts sensor values in the MACPayload and
  44. // sends these values up to the server. For the server it is impossible to know
  45. // whther or not the message comes from a LoRa node or from the gateway.
  46. //
  47. // The example code below adds a battery value in lCode (encoding protocol) but
  48. // of-course you can add any byte string you wish
  49. //
  50. // Parameters:
  51. // - buf: contains the buffer to put the sensor values in (max==xx);
  52. // Returns:
  53. // - The amount of sensor characters put in the buffer
  54. //
  55. // NOTE: The code in LoRaSensors() is provided as an example only.
  56. // The amount of sensor values as well as their message layout may differ
  57. // for each implementation.
  58. // Also, the message format used by this gateway is LoraCode, a message format
  59. // developed by me for sensor values. Each value is uniquely coded with an
  60. // id and a value, and the total message contains its length (less than 64 bytes)
  61. // and a parity value in byte[0] bit 7.
  62. // ----------------------------------------------------------------------------
  63. static int LoRaSensors(uint8_t *buf) {
  64. uint8_t tchars = 1;
  65. buf[0] = 0x86; // 134; User code <lCode + len==3 + Parity
  66. #if _DUSB>=1
  67. if (debug>=0)
  68. Serial.print(F("LoRaSensors:: "));
  69. #endif
  70. #if _BATTERY==1
  71. #if _DUSB>=1
  72. if (debug>=0)
  73. Serial.print(F("Battery "));
  74. #endif
  75. #if defined(ARDUINO_ARCH_ESP8266) || defined(ESP32)
  76. // For ESP there is no standard battery library
  77. // What we do is to measure GPIO35 pin which has a 100K voltage divider
  78. pinMode(35, INPUT);
  79. #if defined(ESP32)
  80. int devider=4095;
  81. #else
  82. int devider=1023;
  83. #endif //ESP32
  84. float volts=3.3 * analogRead(35) / 4095 * 2; // T_Beam connects to GPIO35
  85. #else
  86. // For ESP8266 no sensor defined
  87. float volts=0;
  88. #endif
  89. tchars += lcode.eBattery(volts, buf + tchars);
  90. #endif
  91. #if _GPS==1
  92. #if _DUSB>=1
  93. if (debug>=0)
  94. Serial.print(F("M GPS "));
  95. if (( debug>=1 ) && ( pdebug & P_MAIN )) {
  96. Serial.print("\tLatitude : ");
  97. Serial.println(gps.location.lat(), 5);
  98. Serial.print("\tLongitude : ");
  99. Serial.println(gps.location.lng(), 4);
  100. Serial.print("\tSatellites: ");
  101. Serial.println(gps.satellites.value());
  102. Serial.print("\tAltitude : ");
  103. Serial.print(gps.altitude.feet() / 3.2808);
  104. Serial.println("M");
  105. Serial.print("\tTime : ");
  106. Serial.print(gps.time.hour());
  107. Serial.print(":");
  108. Serial.print(gps.time.minute());
  109. Serial.print(":");
  110. Serial.println(gps.time.second());
  111. }
  112. #endif
  113. smartDelay(1000);
  114. if (millis() > 5000 && gps.charsProcessed() < 10) {
  115. #if _DUSB>=1
  116. Serial.println(F("No GPS data received: check wiring"));
  117. #endif
  118. return(0);
  119. }
  120. // Assuming we have a value, put it in the buf
  121. // The layout of this message is specific to the user,
  122. // so adapt as needed.
  123. tchars += lcode.eGpsL(gps.location.lat(), gps.location.lng(), gps.altitude.value(),
  124. gps.satellites.value(), buf + tchars);
  125. #endif
  126. #if _DUSB>=1
  127. if (debug>=0)
  128. Serial.println();
  129. #endif
  130. // If all sensor data is encoded, we encode the buffer
  131. lcode.eMsg(buf, tchars); // Fill byte 0 with bytecount and Parity
  132. return(tchars); // return the number of bytes added to payload
  133. }
  134. // ----------------------------------------------------------------------------
  135. // XOR()
  136. // perform x-or function for buffer and key
  137. // Since we do this ONLY for keys and X, Y we know that we need to XOR 16 bytes.
  138. //
  139. // ----------------------------------------------------------------------------
  140. static void mXor(uint8_t *buf, uint8_t *key) {
  141. for (uint8_t i = 0; i < 16; ++i) buf[i] ^= key[i];
  142. }
  143. // ----------------------------------------------------------------------------
  144. // SHIFT-LEFT
  145. // Shift the buffer buf left one bit
  146. // Parameters:
  147. // - buf: An array of uint8_t bytes
  148. // - len: Length of the array in bytes
  149. // ----------------------------------------------------------------------------
  150. static void shift_left(uint8_t * buf, uint8_t len) {
  151. while (len--) {
  152. uint8_t next = len ? buf[1] : 0; // len 0 to 15
  153. uint8_t val = (*buf << 1);
  154. if (next & 0x80) val |= 0x01;
  155. *buf++ = val;
  156. }
  157. }
  158. // ----------------------------------------------------------------------------
  159. // generate_subkey
  160. // RFC 4493, para 2.3
  161. // ----------------------------------------------------------------------------
  162. static void generate_subkey(uint8_t *key, uint8_t *k1, uint8_t *k2) {
  163. memset(k1, 0, 16); // Fill subkey1 with 0x00
  164. // Step 1: Assume k1 is an all zero block
  165. AES_Encrypt(k1,key);
  166. // Step 2: Analyse outcome of Encrypt operation (in k1), generate k1
  167. if (k1[0] & 0x80) {
  168. shift_left(k1,16);
  169. k1[15] ^= 0x87;
  170. }
  171. else {
  172. shift_left(k1,16);
  173. }
  174. // Step 3: Generate k2
  175. for (uint8_t i=0; i<16; i++) k2[i]=k1[i];
  176. if (k1[0] & 0x80) { // use k1(==k2) according rfc
  177. shift_left(k2,16);
  178. k2[15] ^= 0x87;
  179. }
  180. else {
  181. shift_left(k2,16);
  182. }
  183. // step 4: Done, return k1 and k2
  184. return;
  185. }
  186. // ----------------------------------------------------------------------------
  187. // MICPACKET()
  188. // Provide a valid MIC 4-byte code (par 2.4 of spec, RFC4493)
  189. // see also https://tools.ietf.org/html/rfc4493
  190. //
  191. // Although our own handler may choose not to interpret the last 4 (MIC) bytes
  192. // of a PHYSPAYLOAD physical payload message of in internal sensor,
  193. // The official TTN (and other) backends will intrpret the complete message and
  194. // conclude that the generated message is bogus.
  195. // So we sill really simulate internal messages coming from the -1ch gateway
  196. // to come from a real sensor and append 4 MIC bytes to every message that are
  197. // perfectly legimate
  198. // Parameters:
  199. // - data: uint8_t array of bytes = ( MHDR | FHDR | FPort | FRMPayload )
  200. // - len: 8=bit length of data, normally less than 64 bytes
  201. // - FrameCount: 16-bit framecounter
  202. // - dir: 0=up, 1=down
  203. //
  204. // B0 = ( 0x49 | 4 x 0x00 | Dir | 4 x DevAddr | 4 x FCnt | 0x00 | len )
  205. // MIC is cmac [0:3] of ( aes128_cmac(NwkSKey, B0 | Data )
  206. //
  207. // ----------------------------------------------------------------------------
  208. uint8_t micPacket(uint8_t *data, uint8_t len, uint16_t FrameCount, uint8_t * NwkSKey, uint8_t dir) {
  209. //uint8_t NwkSKey[16] = _NWKSKEY;
  210. uint8_t Block_B[16];
  211. uint8_t X[16];
  212. uint8_t Y[16];
  213. // ------------------------------------
  214. // build the B block used by the MIC process
  215. Block_B[0]= 0x49; // 1 byte MIC code
  216. Block_B[1]= 0x00; // 4 byte 0x00
  217. Block_B[2]= 0x00;
  218. Block_B[3]= 0x00;
  219. Block_B[4]= 0x00;
  220. Block_B[5]= dir; // 1 byte Direction
  221. Block_B[6]= DevAddr[3]; // 4 byte DevAddr
  222. Block_B[7]= DevAddr[2];
  223. Block_B[8]= DevAddr[1];
  224. Block_B[9]= DevAddr[0];
  225. Block_B[10]= (FrameCount & 0x00FF); // 4 byte FCNT
  226. Block_B[11]= ((FrameCount >> 8) & 0x00FF);
  227. Block_B[12]= 0x00; // Frame counter upper Bytes
  228. Block_B[13]= 0x00; // These are not used so are 0
  229. Block_B[14]= 0x00; // 1 byte 0x00
  230. Block_B[15]= len; // 1 byte len
  231. // ------------------------------------
  232. // Step 1: Generate the subkeys
  233. //
  234. uint8_t k1[16];
  235. uint8_t k2[16];
  236. generate_subkey(NwkSKey, k1, k2);
  237. // ------------------------------------
  238. // Copy the data to a new buffer which is prepended with Block B0
  239. //
  240. uint8_t micBuf[len+16]; // B0 | data
  241. for (uint8_t i=0; i<16; i++) micBuf[i]=Block_B[i];
  242. for (uint8_t i=0; i<len; i++) micBuf[i+16]=data[i];
  243. // ------------------------------------
  244. // Step 2: Calculate the number of blocks for CMAC
  245. //
  246. uint8_t numBlocks = len/16 + 1; // Compensate for B0 block
  247. if ((len % 16)!=0) numBlocks++; // If we have only a part block, take it all
  248. // ------------------------------------
  249. // Step 3: Calculate padding is necessary
  250. //
  251. uint8_t restBits = len%16; // if numBlocks is not a multiple of 16 bytes
  252. // ------------------------------------
  253. // Step 5: Make a buffer of zeros
  254. //
  255. memset(X, 0, 16);
  256. // ------------------------------------
  257. // Step 6: Do the actual encoding according to RFC
  258. //
  259. for(uint8_t i= 0x0; i < (numBlocks - 1); i++) {
  260. for (uint8_t j=0; j<16; j++) Y[j] = micBuf[(i*16)+j];
  261. mXor(Y, X);
  262. AES_Encrypt(Y, NwkSKey);
  263. for (uint8_t j=0; j<16; j++) X[j] = Y[j];
  264. }
  265. // ------------------------------------
  266. // Step 4: If there is a rest Block, padd it
  267. // Last block. We move step 4 to the end as we need Y
  268. // to compute the last block
  269. //
  270. if (restBits) {
  271. for (uint8_t i=0; i<16; i++) {
  272. if (i< restBits) Y[i] = micBuf[((numBlocks-1)*16)+i];
  273. if (i==restBits) Y[i] = 0x80;
  274. if (i> restBits) Y[i] = 0x00;
  275. }
  276. mXor(Y, k2);
  277. }
  278. else {
  279. for (uint8_t i=0; i<16; i++) {
  280. Y[i] = micBuf[((numBlocks-1)*16)+i];
  281. }
  282. mXor(Y, k1);
  283. }
  284. mXor(Y, X);
  285. AES_Encrypt(Y,NwkSKey);
  286. // ------------------------------------
  287. // Step 7: done, return the MIC size.
  288. // Only 4 bytes are returned (32 bits), which is less than the RFC recommends.
  289. // We return by appending 4 bytes to data, so there must be space in data array.
  290. //
  291. data[len+0]=Y[0];
  292. data[len+1]=Y[1];
  293. data[len+2]=Y[2];
  294. data[len+3]=Y[3];
  295. return 4;
  296. }
  297. #if _CHECK_MIC==1
  298. // ----------------------------------------------------------------------------
  299. // CHECKMIC
  300. // Function to check the MIC computed for existing messages and for new messages
  301. // Parameters:
  302. // - buf: LoRa buffer to check in bytes, last 4 bytes contain the MIC
  303. // - len: Length of buffer in bytes
  304. // - key: Key to use for MIC. Normally this is the NwkSKey
  305. //
  306. // ----------------------------------------------------------------------------
  307. static void checkMic(uint8_t *buf, uint8_t len, uint8_t *key) {
  308. uint8_t cBuf[len+1];
  309. uint8_t NwkSKey[16] = _NWKSKEY;
  310. if (debug>=2) {
  311. Serial.print(F("old="));
  312. for (uint8_t i=0; i<len; i++) {
  313. printHexDigit(buf[i]);
  314. Serial.print(' ');
  315. }
  316. Serial.println();
  317. }
  318. for (uint8_t i=0; i<len-4; i++) cBuf[i] = buf[i];
  319. len -=4;
  320. uint16_t FrameCount = ( cBuf[7] * 256 ) + cBuf[6];
  321. len += micPacket(cBuf, len, FrameCount, NwkSKey, 0);
  322. if (debug>=2) {
  323. Serial.print(F("new="));
  324. for (uint8_t i=0; i<len; i++) {
  325. printHexDigit(cBuf[i]);
  326. Serial.print(' ');
  327. }
  328. Serial.println();
  329. }
  330. // Mic is only checked, but len is not corrected
  331. }
  332. #endif //_CHECK_MIC
  333. // ----------------------------------------------------------------------------
  334. // SENSORPACKET
  335. // The gateway may also have local sensors that need reporting.
  336. // We will generate a message in gateway-UDP format for upStream messaging
  337. // so that for the backend server it seems like a LoRa node has reported a
  338. // sensor value.
  339. //
  340. // NOTE: We do not need ANY LoRa functions here since we are on the gateway.
  341. // We only need to send a gateway message upstream that looks like a node message.
  342. //
  343. // NOTE:: This function does encrypt the sensorpayload, and the backend
  344. // picks it up fine as decoder thinks it is a MAC message.
  345. //
  346. // Par 4.0 LoraWan spec:
  347. // PHYPayload = ( MHDR | MACPAYLOAD | MIC )
  348. // which is equal to
  349. // ( MHDR | ( FHDR | FPORT | FRMPAYLOAD ) | MIC )
  350. //
  351. // This function makes the totalpackage and calculates MIC
  352. // The maximum size of the message is: 12 + ( 9 + 2 + 64 ) + 4
  353. // So message size should be lass than 128 bytes if Payload is limited to 64 bytes.
  354. //
  355. // return value:
  356. // - On success returns the number of bytes to send
  357. // - On error returns -1
  358. // ----------------------------------------------------------------------------
  359. int sensorPacket() {
  360. uint8_t buff_up[512]; // Declare buffer here to avoid exceptions
  361. uint8_t message[64]={ 0 }; // Payload, init to 0
  362. uint8_t mlength = 0;
  363. uint32_t tmst = micros();
  364. struct LoraUp LUP;
  365. uint8_t NwkSKey[16] = _NWKSKEY;
  366. uint8_t AppSKey[16] = _APPSKEY;
  367. uint8_t DevAddr[4] = _DEVADDR;
  368. // Init the other LoraUp fields
  369. LUP.sf = 8; // Send with SF8
  370. LUP.prssi = -50;
  371. LUP.rssicorr = 139;
  372. LUP.snr = 0;
  373. // In the next few bytes the fake LoRa message must be put
  374. // PHYPayload = MHDR | MACPAYLOAD | MIC
  375. // MHDR, 1 byte
  376. // MIC, 4 bytes
  377. // ------------------------------
  378. // MHDR (Para 4.2), bit 5-7 MType, bit 2-4 RFU, bit 0-1 Major
  379. LUP.payLoad[0] = 0x40; // MHDR 0x40 == unconfirmed up message,
  380. // FRU and major are 0
  381. // -------------------------------
  382. // FHDR consists of 4 bytes addr, 1 byte Fctrl, 2 byte FCnt, 0-15 byte FOpts
  383. // We support ABP addresses only for Gateways
  384. LUP.payLoad[1] = DevAddr[3]; // Last byte[3] of address
  385. LUP.payLoad[2] = DevAddr[2];
  386. LUP.payLoad[3] = DevAddr[1];
  387. LUP.payLoad[4] = DevAddr[0]; // First byte[0] of Dev_Addr
  388. LUP.payLoad[5] = 0x00; // FCtrl is normally 0
  389. LUP.payLoad[6] = frameCount % 0x100; // LSB
  390. LUP.payLoad[7] = frameCount / 0x100; // MSB
  391. // -------------------------------
  392. // FPort, either 0 or 1 bytes. Must be != 0 for non MAC messages such as user payload
  393. //
  394. LUP.payLoad[8] = 0x01; // FPort must not be 0
  395. LUP.payLength = 9;
  396. // FRMPayload; Payload will be AES128 encoded using AppSKey
  397. // See LoRa spec para 4.3.2
  398. // You can add any byte string below based on you personal choice of sensors etc.
  399. //
  400. // Payload bytes in this example are encoded in the LoRaCode(c) format
  401. uint8_t PayLength = LoRaSensors((uint8_t *)(LUP.payLoad + LUP.payLength));
  402. #if _DUSB>=1
  403. if ((debug>=2) && (pdebug & P_RADIO )) {
  404. Serial.print(F("old: "));
  405. for (int i=0; i<PayLength; i++) {
  406. Serial.print(LUP.payLoad[i],HEX);
  407. Serial.print(' ');
  408. }
  409. Serial.println();
  410. }
  411. #endif
  412. // we have to include the AES functions at this stage in order to generate LoRa Payload.
  413. uint8_t CodeLength = encodePacket((uint8_t *)(LUP.payLoad + LUP.payLength), PayLength, (uint16_t)frameCount, DevAddr, AppSKey, 0);
  414. #if _DUSB>=1
  415. if ((debug>=2) && (pdebug & P_RADIO )) {
  416. Serial.print(F("new: "));
  417. for (int i=0; i<CodeLength; i++) {
  418. Serial.print(LUP.payLoad[i],HEX);
  419. Serial.print(' ');
  420. }
  421. Serial.println();
  422. }
  423. #endif
  424. LUP.payLength += CodeLength; // length inclusive sensor data
  425. // MIC, Message Integrity Code
  426. // As MIC is used by TTN (and others) we have to make sure that
  427. // framecount is valid and the message is correctly encrypted.
  428. // Note: Until MIC is done correctly, TTN does not receive these messages
  429. // The last 4 bytes are MIC bytes.
  430. //
  431. LUP.payLength += micPacket((uint8_t *)(LUP.payLoad), LUP.payLength, (uint16_t)frameCount, NwkSKey, 0);
  432. #if _DUSB>=1
  433. if ((debug>=2) && (pdebug & P_RADIO )) {
  434. Serial.print(F("mic: "));
  435. for (int i=0; i<LUP.payLength; i++) {
  436. Serial.print(LUP.payLoad[i],HEX);
  437. Serial.print(' ');
  438. }
  439. Serial.println();
  440. }
  441. #endif
  442. // So now our package is ready, and we can send it up through the gateway interface
  443. // Note Be aware that the sensor message (which is bytes) in message will be
  444. // be expanded if the server expects JSON messages.
  445. //
  446. int buff_index = buildPacket(tmst, buff_up, LUP, true);
  447. frameCount++;
  448. statc.msg_ttl++; // XXX Should we count sensor messages as well?
  449. switch(ifreq) {
  450. case 0: statc.msg_ttl_0++; break;
  451. case 1: statc.msg_ttl_1++; break;
  452. case 2: statc.msg_ttl_2++; break;
  453. }
  454. // In order to save the memory, we only write the framecounter
  455. // to EEPROM every 10 values. It also means that we will invalidate
  456. // 10 value when restarting the gateway.
  457. // NOTE: This means that preferences are NOT saved unless >=10 messages have been received.
  458. //
  459. if (( frameCount % 10)==0) writeGwayCfg(CONFIGFILE);
  460. if (buff_index > 512) {
  461. if (debug>0) Serial.println(F("sensorPacket:: ERROR buffer size too large"));
  462. return(-1);
  463. }
  464. #ifdef _TTNSERVER
  465. if (!sendUdp(ttnServer, _TTNPORT, buff_up, buff_index)) {
  466. return(-1);
  467. }
  468. #endif
  469. #ifdef _THINGSERVER
  470. if (!sendUdp(thingServer, _THINGPORT, buff_up, buff_index)) {
  471. return(-1);
  472. }
  473. #endif
  474. #if _DUSB>=1
  475. // If all is right, we should after decoding (which is the same as encoding) get
  476. // the original message back again.
  477. if ((debug>=2) && (pdebug & P_RADIO )) {
  478. CodeLength = encodePacket((uint8_t *)(LUP.payLoad + 9), PayLength, (uint16_t)frameCount-1, DevAddr, AppSKey, 0);
  479. Serial.print(F("rev: "));
  480. for (int i=0; i<CodeLength; i++) {
  481. Serial.print(LUP.payLoad[i],HEX);
  482. Serial.print(' ');
  483. }
  484. Serial.print(F(", addr="));
  485. for (int i=0; i<4; i++) {
  486. Serial.print(DevAddr[i],HEX);
  487. Serial.print(' ');
  488. }
  489. Serial.println();
  490. }
  491. #endif
  492. if (_cad) {
  493. // Set the state to CAD scanning after sending a packet
  494. _state = S_SCAN; // Inititialise scanner
  495. sf = SF7;
  496. cadScanner();
  497. }
  498. else {
  499. // Reset all RX lora stuff
  500. _state = S_RX;
  501. rxLoraModem();
  502. }
  503. return(buff_index);
  504. }
  505. #endif //GATEWAYNODE==1
  506. #if (GATEWAYNODE==1) || (_LOCALSERVER==1)
  507. // ----------------------------------------------------------------------------
  508. // ENCODEPACKET
  509. // In Sensor mode, we have to encode the user payload before sending.
  510. // The same applies to decoding packages in the payload for _LOCALSERVER.
  511. // The library files for AES are added to the library directory in AES.
  512. // For the moment we use the AES library made by ideetron as this library
  513. // is also used in the LMIC stack and is small in size.
  514. //
  515. // The function below follows the LoRa spec exactly.
  516. //
  517. // The resulting mumber of Bytes is returned by the functions. This means
  518. // 16 bytes per block, and as we add to the last block we also return 16
  519. // bytes for the last block.
  520. //
  521. // The LMIC code does not do this, so maybe we shorten the last block to only
  522. // the meaningful bytes in the last block. This means that encoded buffer
  523. // is exactly as big as the original message.
  524. //
  525. // NOTE:: Be aware that the LICENSE of the used AES library files
  526. // that we call with AES_Encrypt() is GPL3. It is used as-is,
  527. // but not part of this code.
  528. //
  529. // cmac = aes128_encrypt(K, Block_A[i])
  530. // ----------------------------------------------------------------------------
  531. uint8_t encodePacket(uint8_t *Data, uint8_t DataLength, uint16_t FrameCount, uint8_t *DevAddr, uint8_t *AppSKey, uint8_t Direction) {
  532. #if _DUSB>=1
  533. if (( debug>=2 ) && ( pdebug & P_GUI )) {
  534. Serial.print(F("G encodePacket:: DevAddr="));
  535. for (int i=0; i<4; i++ ) { Serial.print(DevAddr[i],HEX); Serial.print(' '); }
  536. Serial.print(F("G encodePacket:: AppSKey="));
  537. for (int i=0; i<16; i++ ) { Serial.print(AppSKey[i],HEX); Serial.print(' '); }
  538. Serial.println();
  539. }
  540. #endif
  541. //unsigned char AppSKey[16] = _APPSKEY ; // see configGway.h
  542. uint8_t i, j;
  543. uint8_t Block_A[16];
  544. uint8_t bLen=16; // Block length is 16 except for last block in message
  545. uint8_t restLength = DataLength % 16; // We work in blocks of 16 bytes, this is the rest
  546. uint8_t numBlocks = DataLength / 16; // Number of whole blocks to encrypt
  547. if (restLength>0) numBlocks++; // And add block for the rest if any
  548. for(i = 1; i <= numBlocks; i++) {
  549. Block_A[0] = 0x01;
  550. Block_A[1] = 0x00;
  551. Block_A[2] = 0x00;
  552. Block_A[3] = 0x00;
  553. Block_A[4] = 0x00;
  554. Block_A[5] = Direction; // 0 is uplink
  555. Block_A[6] = DevAddr[3]; // Only works for and with ABP
  556. Block_A[7] = DevAddr[2];
  557. Block_A[8] = DevAddr[1];
  558. Block_A[9] = DevAddr[0];
  559. Block_A[10] = (FrameCount & 0x00FF);
  560. Block_A[11] = ((FrameCount >> 8) & 0x00FF);
  561. Block_A[12] = 0x00; // Frame counter upper Bytes
  562. Block_A[13] = 0x00; // These are not used so are 0
  563. Block_A[14] = 0x00;
  564. Block_A[15] = i;
  565. // Encrypt and calculate the S
  566. AES_Encrypt(Block_A, AppSKey);
  567. // Last block? set bLen to rest
  568. if ((i == numBlocks) && (restLength>0)) bLen = restLength;
  569. for(j = 0; j < bLen; j++) {
  570. *Data = *Data ^ Block_A[j];
  571. Data++;
  572. }
  573. }
  574. //return(numBlocks*16); // Do we really want to return all 16 bytes in lastblock
  575. return(DataLength); // or only 16*(numBlocks-1)+bLen;
  576. }
  577. #endif