LoRaCode.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. // LoRa encoding and decoding functions
  2. // Copyright (c) 2016, 2017 Maarten Westenberg (mw12554@hotmail.com)
  3. // Version 1.2.0
  4. // Date: 2016-10-23
  5. // Version 1.2.0 on April 20, 2017
  6. //
  7. // All rights reserved. This program and the accompanying materials
  8. // are made available under the terms of the MIT License
  9. // which accompanies this distribution, and is available at
  10. // https://opensource.org/licenses/mit-license.php
  11. //
  12. // Author: Maarten Westenberg
  13. //
  14. // The protocols used in this code:
  15. // 1. LoRA Specification version V1.0 and V1.1 for Gateway-Node communication
  16. //
  17. // 2. Semtech Basic communication protocol between Lora gateway and server version 3.0.0
  18. // https://github.com/Lora-net/packet_forwarder/blob/master/PROTOCOL.TXT
  19. //
  20. // Notes:
  21. // The lCode specification is documented on a sparate page on github.
  22. //
  23. // Todo:
  24. // The luminescense is read as a 16-bit value in the library and converted to
  25. // a float value in order to get proper scaling etc. In the lCode lib it is
  26. // coded as a 2-byte value over the air, which might be incorrect for lux values
  27. // over 650 lux (which IS posible since bright daylight has more than 1000 lux).
  28. // So XXX we have to add another byte to cover values above 65
  29. // ----------------------------------------------------------------------------------------
  30. #define DEBUG 0
  31. #if defined(__AVR__)
  32. #include <avr/pgmspace.h>
  33. #include <Arduino.h>
  34. #include <Battery.h>
  35. #elif defined(ARDUINO_ARCH_ESP8266) | defined(ESP32)
  36. #include <ESP.h>
  37. #elif defined(__MKL26Z64__)
  38. #include <Arduino.h>
  39. #else
  40. #error Unknown architecture in aes.cpp
  41. #endif
  42. #include "LoRaCode.h"
  43. int ldebug=DEBUG;
  44. // --------------------------------------------------------------------------------
  45. // Encode Temperature.
  46. // We use 2 bytes for temperature, first contains the integer partial_sort.
  47. // We add 100 so we effectively will measure temperatures between -100 and 154 degrees.
  48. // Second byte contains the fractional part in 2 decimals (00-99).
  49. // --------------------------------------------------------------------------------
  50. int LoRaCode::eTemperature(float val, byte *msg) {
  51. int len=0;
  52. byte i= (byte) (val+100); // Integer part
  53. byte f= (byte) ( ((float)(val - (float)i -100)) * 100); // decimal part
  54. msg[len++] = ((byte)O_TEMP << 2) | 0x01; // Last 2 bits are 0x01, two bytes
  55. msg[len++] = i;
  56. msg[len++] = f;
  57. #if DEBUG>0
  58. if (ldebug >=1) {
  59. Serial.print(F("lcode:: Add Temperature "));
  60. Serial.print(i-100); // For readibility
  61. Serial.print(".");
  62. Serial.println(f);
  63. }
  64. #endif
  65. return(len);
  66. }
  67. // --------------------------------------------------------------------------------
  68. // Code Humidity in the *msg
  69. // The humidity of the sensor is between 0-100%, we encode this value * 2 so that
  70. // byte value is betwene 0 and 199.
  71. // --------------------------------------------------------------------------------
  72. int LoRaCode::eHumidity(float val, byte *msg) {
  73. int len=0;
  74. byte i = (byte) ((float)val *2); // Value times 2
  75. msg[len++] = ((byte)O_HUMI << 2) | 0x00; // Last 2 bits are 0x00, one byte
  76. msg[len++] = i; //
  77. #if DEBUG>0
  78. if (ldebug >=1) {
  79. Serial.print(F("lcode:: Add Humidity "));
  80. Serial.println((float)(i/2)); // For readibility
  81. }
  82. #endif
  83. return(len);
  84. }
  85. // --------------------------------------------------------------------------------
  86. // Code the Airpressure.
  87. // The coded value is the measured value minus 900. This gives an airpressure
  88. // range from 850-1104
  89. // --------------------------------------------------------------------------------
  90. int LoRaCode::eAirpressure(float val, byte *msg) {
  91. int len=0;
  92. byte i = (byte) ((float)val -850); // Value times 2
  93. msg[len++] = ((byte)O_AIRP << 2) | 0x00; // Last 2 bits are 0x00, one byte
  94. msg[len++] = i; //
  95. #if DEBUG>0
  96. if (ldebug >=1) {
  97. Serial.print(F("lcode:: Add Airpressure "));
  98. Serial.println((float)(i + 850)); // For readibility
  99. }
  100. #endif
  101. return(len);
  102. }
  103. // --------------------------------------------------------------------------------
  104. // GPS lat and lng encoding
  105. // There are several ways to encode GPS data. Eother by mapping on 3 or 4 bytes of
  106. // Floating, or by just multiplying with 1,000,000 for example (gives 6 digits
  107. // precision which is enough for almost all applications)
  108. // --------------------------------------------------------------------------------
  109. int LoRaCode::eGps(double lat, double lng, byte *msg) {
  110. #if DEBUG>0
  111. if (ldebug>=1) {
  112. Serial.print(F(" LAT: ")); Serial.print(lat,6);
  113. Serial.print(F(" LNG: ")); Serial.println(lng,6);
  114. }
  115. #endif
  116. int len=0;
  117. long factor = 1000000;
  118. msg[len++] = ((byte)O_GPS << 2) | 0x00; // Last 2 bits are 0x00, don't care
  119. const long calculatedLat = (long)(lat * factor);
  120. msg[len++] = (calculatedLat >> (8*3)) & 0xFF;
  121. msg[len++] = (calculatedLat >> (8*2)) & 0xFF;
  122. msg[len++] = (calculatedLat >> (8*1)) & 0xFF;
  123. msg[len++] = (calculatedLat >> (8*0)) & 0xFF;
  124. const long calculatedLng = (long)(lng * factor);
  125. msg[len++] = (calculatedLng >> (8*3)) & 0xFF;
  126. msg[len++] = (calculatedLng >> (8*2)) & 0xFF;
  127. msg[len++] = (calculatedLng >> (8*1)) & 0xFF;
  128. msg[len++] = (calculatedLng >> (8*0)) & 0xFF;
  129. return(len);
  130. }
  131. // --------------------------------------------------------------------------------
  132. // Code the extended GPS format
  133. // latitude and longitude are coded just like the short format
  134. // Altitude is a long containing the altitude in cm
  135. // --------------------------------------------------------------------------------
  136. int LoRaCode::eGpsL(double lat, double lng, long alt, int sat,
  137. byte *msg) {
  138. if (ldebug>=1) {
  139. Serial.print(F(" LAT: ")); Serial.print(lat,6);
  140. Serial.print(F(" LNG: ")); Serial.print(lng,6);
  141. Serial.print(F(" ALT: ")); Serial.print(alt/100);
  142. Serial.print(F(" SAT: ")); Serial.println(sat);
  143. }
  144. int len=0;
  145. long factor = 1000000;
  146. msg[len++] = ((byte)O_GPSL << 2) | 0x00; // Last 2 bits are 0x00, don't care
  147. const long calculatedLat = (long)(lat * factor);
  148. msg[len++] = (calculatedLat >> (8*3)) & 0xFF;
  149. msg[len++] = (calculatedLat >> (8*2)) & 0xFF;
  150. msg[len++] = (calculatedLat >> (8*1)) & 0xFF;
  151. msg[len++] = (calculatedLat >> (8*0)) & 0xFF;
  152. const long calculatedLng = (long)(lng * factor);
  153. msg[len++] = (calculatedLng >> (8*3)) & 0xFF;
  154. msg[len++] = (calculatedLng >> (8*2)) & 0xFF;
  155. msg[len++] = (calculatedLng >> (8*1)) & 0xFF;
  156. msg[len++] = (calculatedLng >> (8*0)) & 0xFF;
  157. const long calculatedAlt = (long)(alt); // Altitude is integer specified in cm (converted later to m)
  158. msg[len++] = (calculatedAlt >> (8*3)) & 0xFF;
  159. msg[len++] = (calculatedAlt >> (8*2)) & 0xFF;
  160. msg[len++] = (calculatedAlt >> (8*1)) & 0xFF;
  161. msg[len++] = (calculatedAlt >> (8*0)) & 0xFF;
  162. msg[len++] = sat & 0xFF; // Positive number, assumed always to be less than 255
  163. return(len);
  164. }
  165. // --------------------------------------------------------------------------------
  166. // Encode the 1-bit PIR value
  167. // --------------------------------------------------------------------------------
  168. int LoRaCode::ePir(int val, byte *msg) {
  169. int i = (byte) ( val );
  170. int len=0; //
  171. msg[len++] = (O_PIR << 2) | 0x00; // Last 2 bits are 0x00, one byte
  172. msg[len++] = i;
  173. return(len);
  174. }
  175. // --------------------------------------------------------------------------------
  176. // Encode Airquality Value.
  177. // Airquality through SDS011 sensors is measured with two float values
  178. // and read as a 10-bit value (0-1024). We use a 2 x 2-byte value
  179. // --------------------------------------------------------------------------------
  180. int LoRaCode::eAirquality(int pm25, int pm10, byte *msg) {
  181. int len=0;
  182. uint16_t val = (uint16_t) (pm25);
  183. msg[len++] = (O_AQ << 2) | 0x03; // Last 2 bits are 0x03, so 4 bytes data
  184. msg[len++] = (val >> 8) & 0xFF;
  185. msg[len++] = val & 0xFF;
  186. val = (uint16_t) (pm10);
  187. msg[len++] = (val >> 8) & 0xFF;
  188. msg[len++] = val & 0xFF;
  189. #if DEBUG>0
  190. if (ldebug >=1) {
  191. Serial.print(F("lcode:: Add Airquality <"));
  192. Serial.print(len);
  193. Serial.print(F("> "));
  194. Serial.println(val); // For readibility
  195. }
  196. #endif
  197. return(len);
  198. }
  199. // --------------------------------------------------------------------------------
  200. // Encode a Multi-Button sensor. This sensor is a concentrator that receives
  201. // several sensor values over 433MHz and retransmits them over LoRa
  202. // The LoRa sensor node contains the main address (LoRa id), the concentrated
  203. // sendors have their own unique address/channel combination.
  204. // --------------------------------------------------------------------------------
  205. int LoRaCode::eMbuttons(byte val, unsigned long address, unsigned short channel, byte *msg) {
  206. int len=0;
  207. msg[len++] = (O_MB << 2) | 0x00; // Several bytes, do not care
  208. msg[len++] = val; // First code the value
  209. msg[len++] = (address >> (8*3)) & 0xFF; // Address
  210. msg[len++] = (address >> (8*2)) & 0xFF;
  211. msg[len++] = (address >> (8*1)) & 0xFF;
  212. msg[len++] = (address >> (8*0)) & 0xFF;
  213. msg[len++] = (channel >> (8*1)) & 0xFF; // Channel
  214. msg[len++] = (channel >> (8*0)) & 0xFF;
  215. #if DEBUG>0
  216. if (ldebug >=1) {
  217. Serial.print(F("lcode:: Add Multi-Button "));
  218. Serial.println(val); // For readibility
  219. }
  220. #endif
  221. return(len);
  222. }
  223. // --------------------------------------------------------------------------------
  224. // Moisture detection with two metal sensors in fluid or soil
  225. //
  226. // --------------------------------------------------------------------------------
  227. int LoRaCode::eMoist(int val, byte *msg) {
  228. int len=0;
  229. msg[len++] = (O_MOIST << 2) | 0x00; // Last 2 bits are 0x00, 1 byte
  230. msg[len++] = (val / 4 ) & 0xFF;
  231. #if DEBUG>0
  232. if (ldebug >=1) {
  233. Serial.print(F("lcode:: Add Moisture "));
  234. Serial.println(val); // For readibility
  235. }
  236. #endif
  237. return(len);
  238. }
  239. // --------------------------------------------------------------------------------
  240. // Luminescense detection with two metal sensors in fluid or soil
  241. // The value to be decoded is 2-byte value which gives
  242. // an integer resolution from 0 to 65535
  243. // It is possible to add a third byte for extra resolution (2 decimals).
  244. // --------------------------------------------------------------------------------
  245. int LoRaCode::eLuminescense(float val, byte *msg) {
  246. int len=0;
  247. uint16_t lux = (uint16_t) (val);
  248. // now determine the fraction for a third byte
  249. msg[len++] = (O_LUMI << 2) | 0x01; // Last 2 bits are 0x00, 2 bytes resolution
  250. msg[len++] = (lux >> (8*1)) & 0xFF; // LSB
  251. msg[len++] = (lux >> (8*0)) & 0xFF;
  252. #if DEBUG>0
  253. if (ldebug >=1) {
  254. Serial.print(F("lcode:: Add Lumi "));
  255. Serial.println(val); // For readibility
  256. }
  257. #endif
  258. return(len);
  259. }
  260. int LoRaCode::eLuminescenseL(float val, byte *msg) {
  261. int len=0;
  262. uint16_t lux = (uint16_t) (val);
  263. // now determine the fraction for a third byte
  264. uint8_t frac = (uint8_t) ((val-lux) * 100);
  265. msg[len++] = (O_LUMI << 2) | 0x02; // Last 2 bits are 0x00, 3 bytes resolution
  266. msg[len++] = (lux >> (8*1)) & 0xFF; // LSB
  267. msg[len++] = (lux >> (8*0)) & 0xFF;
  268. msg[len++] = (frac) & 0xFF;
  269. #if DEBUG>0
  270. if (ldebug >=1) {
  271. Serial.print(F("lcode:: Add Lumi L="));
  272. Serial.print(lux); // For readibility
  273. Serial.print('.');
  274. Serial.println(frac); // For readibility
  275. }
  276. #endif
  277. return(len);
  278. }
  279. // --------------------------------------------------------------------------------
  280. // Distance detection
  281. // In this case we use 2 bytes for 0-65535 mm (which is more than we need)
  282. // NOTE: The sensor will report in mm resolution, but the server side
  283. // will decode in cm resolution with one decimal fraction (if available)
  284. // --------------------------------------------------------------------------------
  285. int LoRaCode::eDistance(int val, byte *msg) {
  286. int len=0;
  287. msg[len++] = (O_DIST << 2) | 0x01; // Last 2 bits are 0x00, 2 bytes resolution
  288. msg[len++] = (val >> (8*1)) & 0xFF; // LSB
  289. msg[len++] = (val >> (8*0)) & 0xFF;
  290. #if DEBUG>0
  291. if (ldebug >=1) {
  292. Serial.print(F("lcode:: Add Dist "));
  293. Serial.println(val); // For readibility
  294. }
  295. #endif
  296. return(len);
  297. }
  298. // --------------------------------------------------------------------------------
  299. // Encode Gas concentration Value.
  300. // Airquality through MQxx or AQxx sensors is measured through the Analog port
  301. // and read as a 10-bit value (0-1024). We use a 2-byte value
  302. // In order to tell the server which sensor is reporting (we can have several)
  303. // --------------------------------------------------------------------------------
  304. int LoRaCode::eGas(int val, byte *msg) {
  305. int len=0;
  306. msg[len++] = (O_GAS << 2) | 0x01; // Last 2 bits are 0x01, 2 bytes
  307. msg[len++] = (val >> 8) & 0xFF;
  308. msg[len++] = val & 0xFF;
  309. #if DEBUG>0
  310. if (ldebug >=1) {
  311. Serial.print(F("lcode:: Add Gas "));
  312. Serial.println(val); // For readibility
  313. }
  314. #endif
  315. return(len);
  316. }
  317. // --------------------------------------------------------------------------------
  318. // Encode Battery Value.
  319. // Battery Voltage is between 2 and 4 Volts (sometimes 12V)
  320. // We therefore multiply by 20, reported values are between 1 and 255, so
  321. // sensor values between 0,05 and 12.75 Volts
  322. // --------------------------------------------------------------------------------
  323. int LoRaCode::eBattery(float val, byte *msg) {
  324. int len=0;
  325. int i = (byte) ((float)val *20); // Value times 20
  326. msg[len++] = (O_BATT << 2) | 0x00; // Last 2 bits are 0x00, one byte
  327. msg[len++] = i;
  328. #if DEBUG>0
  329. if (ldebug >=1) {
  330. Serial.print(F("lcode:: Add Battery "));
  331. Serial.println((float)(i/20)); // For readibility
  332. }
  333. #endif
  334. return(len);
  335. }
  336. // --------------------------------------------------------------------------------
  337. // Encode AD Converter value for pin adc0 and adv1
  338. // Battery Voltage is between 2 and 4 Volts (sometimes 12V)
  339. // We therefore multiply by 20, reported values are between 1 and 255, so
  340. // sensor values between 0,05 and 12.75 Volts
  341. // --------------------------------------------------------------------------------
  342. int LoRaCode::eAdc0(int val, byte *msg) {
  343. int len=0;
  344. msg[len++] = (O_ADC0 << 2) | 0x00; // Last 2 bits are 0x00, 1 byte
  345. msg[len++] = (val / 4 ) & 0xFF;
  346. #if DEBUG>0
  347. if (ldebug >=1) {
  348. Serial.print(F("lcode:: Add Adc0 "));
  349. Serial.println(val); // For readibility
  350. }
  351. #endif
  352. return(len);
  353. }
  354. int LoRaCode::eAdc1(int val, byte *msg) {
  355. int len=0;
  356. msg[len++] = (O_ADC1 << 2) | 0x00; // Last 2 bits are 0x00, 1 byte
  357. msg[len++] = (val / 4 ) & 0xFF;
  358. #if DEBUG>0
  359. if (ldebug >=1) {
  360. Serial.print(F("lcode:: Add Adc1 "));
  361. Serial.println(val); // For readibility
  362. }
  363. #endif
  364. return(len);
  365. }
  366. // --------------------------------------------------------------------------------
  367. // Function to encode the sensor values to the Payload message
  368. // Input: Opcode and Value
  369. // Output: msg
  370. // return: Number of bytes added to msg
  371. // --------------------------------------------------------------------------------
  372. int LoRaCode::eVal (int opcode, byte *val, byte *msg) {
  373. int len=0;
  374. switch (opcode) {
  375. case O_TEMP: // Temperature
  376. len += eTemperature((float) *val, msg);
  377. break;
  378. case O_HUMI: // Humidity
  379. len += eHumidity((float) *val, msg);
  380. break;
  381. case O_AIRP: // Airpressure
  382. len += eAirpressure((float) *val, msg);
  383. break;
  384. case O_GPS: // GPS short Info
  385. //len += eGps(lat, lng, msg);
  386. break;
  387. case O_PIR: // PIR
  388. len += ePir((int) *val, msg);
  389. break;
  390. case O_MOIST: // Moisture
  391. len += eMoist((int) *val, msg);
  392. break;
  393. case O_LUMI: // Luminescense
  394. len += eLuminescense((int) *val, msg);
  395. break;
  396. case O_BATT: // Battery
  397. len += eBattery((float) *val, msg);
  398. break;
  399. default:
  400. #if DEBUG>0
  401. Serial.println("lCode:: Error opcode not known");
  402. #endif
  403. break;
  404. }
  405. return(len);
  406. }
  407. // --------------------------------------------------------------------------------
  408. // Function to encode the Payload message (final step)
  409. // This function will modify the first byte of the string to encode the length
  410. // and the parity. Payload begins at position 1, byte 0 is reserved
  411. // --------------------------------------------------------------------------------
  412. bool LoRaCode::eMsg (byte * msg, int len) {
  413. unsigned char par = 0;
  414. if (len > 64) {
  415. #if DEBUG>0
  416. Serial.println("lCodeMsg:: Error, string to long");
  417. #endif
  418. return(false);
  419. }
  420. #if DEBUG>0
  421. if (ldebug>=1) {Serial.print(F("LCodeMsg:: <")); Serial.print(len); Serial.print(F("> ")); }
  422. #endif
  423. // else we probably have a good message
  424. msg[0] = ( len << 1 ) | (0x80);
  425. // Now we have to calculate the Parity for the message
  426. for (int i=0; i< len; i++) {
  427. byte cc = msg[i];
  428. par ^= cc;
  429. }
  430. // Now we have par as one byte and need to XOR the bits of that byte.
  431. unsigned char pp = 8; // width of byte in #bits
  432. while (pp > 1) {
  433. par ^= par >> (pp/2);
  434. pp -= pp/2;
  435. }
  436. if (par & 0x01) { // if odd number of 1's in string
  437. #if DEBUG>0
  438. if (ldebug>=1) Serial.print(F(" odd "));
  439. #endif
  440. msg[0] |= 0x01; // Add another 1 to make parity even
  441. }
  442. else {
  443. #if DEBUG>0
  444. if (ldebug>=1) Serial.print(F(" even "));
  445. #endif
  446. }
  447. return(true);
  448. }
  449. // --------------------------------------------------------------------------------
  450. // Print an encoded string
  451. // --------------------------------------------------------------------------------
  452. void LoRaCode::lPrint (byte *msg, int len) {
  453. Serial.print(F("lCode: "));
  454. for (int i=0; i< len; i++) {
  455. if (msg[i]<10) Serial.print('0');
  456. Serial.print(msg[i],HEX);
  457. Serial.print(" ");
  458. }
  459. Serial.println();
  460. }
  461. // --------------------------------------------------------------------------------
  462. // Decode first byte of message containing length
  463. // --------------------------------------------------------------------------------
  464. int LoRaCode::dLen (byte *msg) {
  465. if ( ! (msg[0] & 0x80 )) return(-1); // Error
  466. int len = msg[0] & 0x7F; // Blank out first bit which is always 1 with LoRaCode
  467. return (len >> 1);
  468. }
  469. // --------------------------------------------------------------------------------
  470. // Decode message. One function for all, always returns a float
  471. // We expect that the buffer is large enough and will contain all bytes required
  472. // by that specific encoding
  473. // XXX This function needs finishig (never used at the moment)
  474. // PARAMETERS:
  475. // msg: Contains the message as a byte string
  476. // val: contains the decoded value as a float (xxx)
  477. // mode: Contains the opcode of the decoded command
  478. // RETURN:
  479. // The number of bytes read from the buffer
  480. // --------------------------------------------------------------------------------
  481. int LoRaCode::dMsg (byte *msg, byte *val, byte *mode) {
  482. float res;
  483. byte len = msg[0] & 0x03; // Last 2 bits
  484. *mode = (byte) (msg[0] >> 2);
  485. switch (*mode) {
  486. case O_TEMP:
  487. *val = (float) msg[1]- 100 + ( (float) msg[2] / 100);
  488. return(3);
  489. break;
  490. case O_HUMI:
  491. *val = (float) msg[1] / 2;
  492. return(2);
  493. break;
  494. case O_AIRP:
  495. *val = 0;
  496. return(2);
  497. break;
  498. case O_GPS: // Returning one float does not work for GPS. function never used
  499. *val = 0;
  500. return(9);
  501. break;
  502. case O_GPSL:
  503. *val = 0;
  504. return(14);
  505. break;
  506. case O_PIR:
  507. *val = msg[1];
  508. return(2);
  509. break;
  510. case O_AQ:
  511. *val = 0;
  512. return(3);
  513. break;
  514. case O_BATT:
  515. *val = (float) msg[1] / 20;
  516. return(2);
  517. break;
  518. case O_STAT:
  519. *val = 0;
  520. return(1);
  521. case O_1CH:
  522. *val = msg[1];
  523. return(2);
  524. break;
  525. case O_SF:
  526. *val = msg[1];
  527. return(2);
  528. break;
  529. case O_TIM: // Timing of the wait cyclus
  530. val[0] = msg[1];
  531. val[1] = msg[2];
  532. return(3); // total lengt 2 bytes data + 1 byte opcode
  533. break;
  534. default:
  535. return(0);
  536. }
  537. return (0);
  538. }
  539. // Variable declaration
  540. LoRaCode lcode;