Advertisement
Guest User

Untitled

a guest
Feb 14th, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 29.51 KB | None | 0 0
  1. // Copyright © 2017 The Things Network
  2. // Use of this source code is governed by the MIT license that can be found in the LICENSE file.
  3.  
  4. #include "TheThingsNetwork.h"
  5.  
  6. #define debugPrintLn(...)                \
  7.   {                                      \
  8.     if (debugStream)                     \
  9.       debugStream->println(__VA_ARGS__); \
  10.   }
  11. #define debugPrint(...)                \
  12.   {                                    \
  13.     if (debugStream)                   \
  14.       debugStream->print(__VA_ARGS__); \
  15.   }
  16.  
  17. #define TTN_HEX_CHAR_TO_NIBBLE(c) ((c >= 'A') ? (c - 'A' + 0x0A) : (c - '0'))
  18. #define TTN_HEX_PAIR_TO_BYTE(h, l) ((TTN_HEX_CHAR_TO_NIBBLE(h) << 4) + TTN_HEX_CHAR_TO_NIBBLE(l))
  19.  
  20. const char ok[]  = "ok";
  21. const char on[]  = "on";
  22. const char off[]  = "off";
  23. const char accepted[]  = "accepted";
  24. const char mac_tx_ok[]  = "mac_tx_ok";
  25. const char mac_rx[]  = "mac_rx";
  26. const char rn2483[]  = "RN2483";
  27.  
  28. const char *const compare_table[]  = {ok, on, off, accepted, mac_tx_ok, mac_rx, rn2483};
  29.  
  30. #define CMP_OK 0
  31. #define CMP_ON 1
  32. #define CMP_OFF 2
  33. #define CMP_ACCEPTED 3
  34. #define CMP_MAC_TX_OK 4
  35. #define CMP_MAC_RX 5
  36. #define CMP_RN2483 6
  37.  
  38. #define SENDING "Sending: "
  39. #define SEND_MSG "\r\n"
  40.  
  41. const char eui[]  = "EUI: ";
  42. const char battery[]  = "Battery: ";
  43. const char appEui[]  = "AppEUI: ";
  44. const char devEui[]  = "DevEUI: ";
  45. const char band[]  = "Band: ";
  46. const char data_rate[]  = "Data Rate: ";
  47. const char rx_delay_1[]  = "RX Delay 1: ";
  48. const char rx_delay_2[]  = "RX Delay 2: ";
  49. const char version[]  = "Version: ";
  50. const char model[]  = "Model: ";
  51. const char devaddr[]  = "DevAddr: ";
  52.  
  53. const char *const show_table[]  = {eui, battery, appEui, devEui, band, data_rate, rx_delay_1, rx_delay_2, version, model, devaddr};
  54.  
  55. #define SHOW_EUI 0
  56. #define SHOW_BATTERY 1
  57. #define SHOW_APPEUI 2
  58. #define SHOW_DEVEUI 3
  59. #define SHOW_BAND 4
  60. #define SHOW_DATA_RATE 5
  61. #define SHOW_RX_DELAY_1 6
  62. #define SHOW_RX_DELAY_2 7
  63. #define SHOW_VERSION 8
  64. #define SHOW_MODEL 9
  65. #define SHOW_DEVADDR 10
  66.  
  67. const char invalid_sf[]  = "Invalid SF";
  68. const char invalid_fp[]  = "Invalid frequency plan";
  69. const char unexpected_response[]  = "Unexpected response: ";
  70. const char send_command_failed[]  = "Send command failed";
  71. const char join_failed[]  = "Send join command failed";
  72. const char join_not_accepted[]  = "Join not accepted: ";
  73. const char personalize_not_accepted[]  = "Personalize not accepted";
  74. const char response_is_not_ok[]  = "Response is not OK: ";
  75. const char error_key_length[]  = "One or more keys are of invalid length.";
  76. const char check_configuration[]  = "Check your coverage, keys and backend status.";
  77.  
  78. const char *const error_msg[]  = {invalid_sf, invalid_fp, unexpected_response, send_command_failed, join_failed, join_not_accepted, personalize_not_accepted, response_is_not_ok, error_key_length, check_configuration};
  79.  
  80. #define ERR_INVALID_SF 0
  81. #define ERR_INVALID_FP 1
  82. #define ERR_UNEXPECTED_RESPONSE 2
  83. #define ERR_SEND_COMMAND_FAILED 3
  84. #define ERR_JOIN_FAILED 4
  85. #define ERR_JOIN_NOT_ACCEPTED 5
  86. #define ERR_PERSONALIZE_NOT_ACCEPTED 6
  87. #define ERR_RESPONSE_IS_NOT_OK 7
  88. #define ERR_KEY_LENGTH 8
  89. #define ERR_CHECK_CONFIGURATION 9
  90.  
  91. const char personalize_accepted[]  = "Personalize accepted. Status: ";
  92. const char join_accepted[]  = "Join accepted. Status: ";
  93. const char successful_transmission[]  = "Successful transmission";
  94. const char successful_transmission_received[]  = "Successful transmission. Received ";
  95.  
  96. const char *const success_msg[]  = {personalize_accepted, join_accepted, successful_transmission, successful_transmission_received};
  97.  
  98. #define SCS_PERSONALIZE_ACCEPTED 0
  99. #define SCS_JOIN_ACCEPTED 1
  100. #define SCS_SUCCESSFUL_TRANSMISSION 2
  101. #define SCS_SUCCESSFUL_TRANSMISSION_RECEIVED 3
  102.  
  103. const char radio_prefix[]  = "radio";
  104. const char radio_set[]  = "set";
  105. const char radio_get[]  = "get";
  106. const char radio_get_bw[]  = "bw";
  107. const char radio_get_prlen[]  = "prlen";
  108. const char radio_get_crc[]  = "crc";
  109. const char radio_get_cr[]  = "cr";
  110. const char radio_get_sf[]  = "sf";
  111.  
  112. const char *const radio_table[]  = {radio_prefix, radio_set, radio_get, radio_get_bw, radio_get_prlen, radio_get_crc, radio_get_cr, radio_get_sf};
  113.  
  114. #define RADIO_PREFIX 0
  115. #define RADIO_SET 1
  116. #define RADIO_GET 2
  117. #define RADIO_GET_BW 3
  118. #define RADIO_GET_PRLEN 4
  119. #define RADIO_GET_CRC 5
  120. #define RADIO_GET_CR 6
  121. #define RADIO_GET_SF 7
  122.  
  123. const char sys_prefix[]  = "sys";
  124. const char sys_sleep[]  = "sleep";
  125. const char sys_reset[]  = "reset";
  126. const char sys_erase_fw[]  = "eraseFW";
  127. const char sys_factory_rst[]  = "factoryRESET";
  128. const char sys_set[]  = "set";
  129. const char sys_get[]  = "get";
  130. const char sys_get_ver[]  = "ver";
  131. const char sys_get_vdd[]  = "vdd";
  132. const char sys_get_hweui[]  = "hweui";
  133. const char sys_set_get_nvm[]  = "nvm";
  134. const char sys_set_pindig[]  = "pindig";
  135.  
  136. const char *const sys_table[]  = {sys_prefix, sys_sleep, sys_reset, sys_erase_fw, sys_factory_rst, sys_set, sys_get, sys_get_ver, sys_get_vdd, sys_get_hweui, sys_set_get_nvm, sys_set_pindig};
  137.  
  138. #define SYS_PREFIX 0
  139. #define SYS_SLEEP 1
  140. #define SYS_RESET 2
  141. #define SYS_ERASE_FW 3
  142. #define SYS_FACTORY_RST 4
  143. #define SYS_SET 5
  144. #define SYS_GET 6
  145. #define SYS_GET_VER 7
  146. #define SYS_GET_VDD 8
  147. #define SYS_GET_HWEUI 9
  148. #define SYS_SET_GET_NVM 10
  149. #define SYS_SET_PINDIG 11
  150.  
  151. const char mac_prefix[]  = "mac";
  152. const char mac_reset[]  = "reset";
  153. const char mac_tx[]  = "tx";
  154. const char mac_join[]  = "join";
  155. const char mac_save[]  = "save";
  156. const char mac_force_enable[]  = "forceENABLE";
  157. const char mac_pause[]  = "pause";
  158. const char mac_resume[]  = "resume";
  159. const char mac_set[]  = "set";
  160. const char mac_get[]  = "get";
  161.  
  162. const char *const mac_table[]  = {mac_prefix, mac_reset, mac_tx, mac_join, mac_save, mac_force_enable, mac_pause, mac_resume, mac_set, mac_get};
  163.  
  164. #define MAC_PREFIX 0
  165. #define MAC_RESET 1
  166. #define MAC_TX 2
  167. #define MAC_JOIN 3
  168. #define MAC_SAVE 4
  169. #define MAC_FORCE_ENABLE 5
  170. #define MAC_PAUSE 6
  171. #define MAC_RESUME 7
  172. #define MAC_SET 8
  173. #define MAC_GET 9
  174.  
  175. const char mac_devaddr[]  = "devaddr";
  176. const char mac_deveui[]  = "deveui";
  177. const char mac_appeui[]  = "appeui";
  178. const char mac_nwkskey[]  = "nwkskey";
  179. const char mac_appskey[]  = "appskey";
  180. const char mac_appkey[]  = "appkey";
  181. const char mac_pwridx[]  = "pwridx";
  182. const char mac_dr[]  = "dr";
  183. const char mac_adr[]  = "adr";
  184. const char mac_bat[]  = "bat";
  185. const char mac_retx[]  = "retx";
  186. const char mac_linkchk[]  = "linkchk";
  187. const char mac_rxdelay1[]  = "rxdelay1";
  188. const char mac_rxdelay2[]  = "rxdelay2";
  189. const char mac_band[]  = "band";
  190. const char mac_ar[]  = "ar";
  191. const char mac_rx2[]  = "rx2";
  192. const char mac_ch[]  = "ch";
  193. const char mac_gwnb[]  = "gwnb";
  194. const char mac_mrgn[]  = "mrgn";
  195.  
  196. const char *const mac_options[]  = {mac_devaddr, mac_deveui, mac_appeui, mac_nwkskey, mac_appskey, mac_appkey, mac_pwridx, mac_dr, mac_adr, mac_bat, mac_retx, mac_linkchk, mac_rxdelay1, mac_rxdelay2, mac_band, mac_ar, mac_rx2, mac_ch, mac_gwnb, mac_mrgn};
  197.  
  198. #define MAC_DEVADDR 0
  199. #define MAC_DEVEUI 1
  200. #define MAC_APPEUI 2
  201. #define MAC_NWKSKEY 3
  202. #define MAC_APPSKEY 4
  203. #define MAC_APPKEY 5
  204. #define MAC_PWRIDX 6
  205. #define MAC_DR 7
  206. #define MAC_ADR 8
  207. #define MAC_BAT 9
  208. #define MAC_RETX 10
  209. #define MAC_LINKCHK 11
  210. #define MAC_RXDELAY1 12
  211. #define MAC_RXDELAY2 13
  212. #define MAC_BAND 14
  213. #define MAC_AR 15
  214. #define MAC_RX2 16
  215. #define MAC_CH 17
  216. #define MAC_GWNB 18
  217. #define MAC_MRGN 19
  218.  
  219. const char mac_join_mode_otaa[]  = "otaa";
  220. const char mac_join_mode_abp[]  = "abp";
  221.  
  222. const char *const mac_join_mode[]  = {mac_join_mode_otaa, mac_join_mode_abp};
  223.  
  224. #define MAC_JOIN_MODE_OTAA 0
  225. #define MAC_JOIN_MODE_ABP 1
  226.  
  227. const char channel_dcycle[]  = "dcycle";
  228. const char channel_drrange[]  = "drrange";
  229. const char channel_freq[]  = "freq";
  230. const char channel_status[]  = "status";
  231.  
  232. const char *const mac_ch_options[]  = {channel_dcycle, channel_drrange, channel_freq, channel_status};
  233.  
  234. #define MAC_CHANNEL_DCYCLE 0
  235. #define MAC_CHANNEL_DRRANGE 1
  236. #define MAC_CHANNEL_FREQ 2
  237. #define MAC_CHANNEL_STATUS 3
  238.  
  239. const char mac_tx_type_cnf[]  = "cnf";
  240. const char mac_tx_type_ucnf[]  = "uncnf";
  241.  
  242. const char *const mac_tx_table[]  = {mac_tx_type_cnf, mac_tx_type_ucnf};
  243.  
  244. #define MAC_TX_TYPE_CNF 0
  245. #define MAC_TX_TYPE_UCNF 1
  246.  
  247. #define MAC_TABLE 0
  248. #define MAC_GET_SET_TABLE 1
  249. #define MAC_JOIN_TABLE 2
  250. #define MAC_CH_TABLE 3
  251. #define MAC_TX_TABLE 4
  252. #define SYS_TABLE 5
  253. #define RADIO_TABLE 6
  254. #define ERR_MESSAGE 7
  255. #define SUCCESS_MESSAGE 8
  256.  
  257. int pgmstrcmp(const char *str1, uint8_t str2Index)
  258. {
  259.   char str2[128];
  260.   strcpy(str2, compare_table[str2Index]);
  261.   return memcmp(str1, str2, min(strlen(str1), strlen(str2)));
  262. }
  263.  
  264. uint8_t digits(uint8_t port)
  265. {
  266.   if (port >= 100)
  267.   {
  268.     return 3;
  269.   }
  270.   else if (port >= 10)
  271.   {
  272.     return 2;
  273.   }
  274.   return 1;
  275. }
  276.  
  277. uint8_t receivedPort(const char *s)
  278. {
  279.   uint8_t port = 0;
  280.   uint8_t i = 0;
  281.   while (s[i] != ' ' && s[i] != '\0')
  282.   {
  283.     port *= 10;
  284.     port += s[i] - 48;
  285.     i++;
  286.   }
  287.   return port;
  288. }
  289.  
  290. TheThingsNetwork::TheThingsNetwork(Stream &modemStream, Stream &debugStream, ttn_fp_t fp, uint8_t sf, uint8_t fsb)
  291. {
  292.   this->debugStream = &debugStream;
  293.   this->modemStream = &modemStream;
  294.   this->modemStream->setTimeout(10000);
  295.   this->fp = fp;
  296.   this->sf = sf;
  297.   this->fsb = fsb;
  298. }
  299.  
  300. size_t TheThingsNetwork::getAppEui(char *buffer, size_t size)
  301. {
  302.   return readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, size);
  303. }
  304.  
  305. size_t TheThingsNetwork::getHardwareEui(char *buffer, size_t size)
  306. {
  307.   return readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, size);
  308. }
  309.  
  310. uint16_t TheThingsNetwork::getVDD()
  311. {
  312.   if (readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer)) > 0) {
  313.     return atoi(buffer);
  314.   }
  315.   return 0;
  316. }
  317.  
  318. void TheThingsNetwork::debugPrintIndex(uint8_t index, const char *value)
  319. {
  320.   char message[100];
  321.   strcpy(message, show_table[index]);
  322.   debugPrint(message);
  323.   if (value)
  324.   {
  325.     debugPrintLn(value);
  326.   }
  327. }
  328.  
  329. void TheThingsNetwork::debugPrintMessage(uint8_t type, uint8_t index, const char *value)
  330. {
  331.   char message[100];
  332.   switch (type)
  333.   {
  334.   case ERR_MESSAGE:
  335.     strcpy(message, error_msg[index]);
  336.     break;
  337.   case SUCCESS_MESSAGE:
  338.     strcpy(message, success_msg[index]);
  339.     break;
  340.   }
  341.   debugPrint(message);
  342.   if (value)
  343.   {
  344.     debugPrintLn(value);
  345.   }
  346.   else
  347.   {
  348.     debugPrintLn();
  349.   }
  350. }
  351.  
  352. void TheThingsNetwork::clearReadBuffer()
  353. {
  354.   while (modemStream->available())
  355.   {
  356.     modemStream->read();
  357.   }
  358. }
  359.  
  360. size_t TheThingsNetwork::readLine(char *buffer, size_t size, uint8_t attempts)
  361. {
  362.   size_t read = 0;
  363.   while (!read && attempts--)
  364.   {
  365.     read = modemStream->readBytesUntil('\n', buffer, size);
  366.   }
  367.   if (attempts<=0)
  368.   { // If attempts is activated return 0 and set RN state marker
  369.     this->needsHardReset = true; // Inform the application about the radio module is not responsive.
  370.     debugPrintLn("No response from RN module.");
  371.     return 0;
  372.   }
  373.   buffer[read - 1] = '\0'; // set \r to \0
  374.   return read;
  375. }
  376.  
  377. size_t TheThingsNetwork::readResponse(uint8_t prefixTable, uint8_t index, char *buffer, size_t size)
  378. {
  379.   clearReadBuffer();
  380.   sendCommand(prefixTable, 0, true, false);
  381.   sendCommand(prefixTable, index, false, false);
  382.   modemStream->write(SEND_MSG);
  383.   return readLine(buffer, size);
  384. }
  385.  
  386. size_t TheThingsNetwork::readResponse(uint8_t prefixTable, uint8_t indexTable, uint8_t index, char *buffer, size_t size)
  387. {
  388.   clearReadBuffer();
  389.   sendCommand(prefixTable, 0, true, false);
  390.   sendCommand(MAC_TABLE, MAC_GET, true, false);
  391.   sendCommand(indexTable, index, false, false);
  392.   modemStream->write(SEND_MSG);
  393.   return readLine(buffer, size);
  394. }
  395.  
  396. void TheThingsNetwork::autoBaud()
  397. {
  398.   // Courtesy of @jpmeijers
  399.   modemStream->setTimeout(2000);
  400.   uint8_t attempts = 10;
  401.   size_t length = 0;
  402.   while (attempts-- && length == 0)
  403.   {
  404.     delay(100);
  405.     modemStream->write((byte)0x00);
  406.     modemStream->write(0x55);
  407.     modemStream->write(SEND_MSG);
  408.     sendCommand(SYS_TABLE, 0, true, false);
  409.     sendCommand(SYS_TABLE, SYS_GET, true, false);
  410.     sendCommand(SYS_TABLE, SYS_GET_VER, false, false);
  411.     modemStream->write(SEND_MSG);
  412.     length = modemStream->readBytesUntil('\n', buffer, sizeof(buffer));
  413.   }
  414.   delay(100);
  415.   clearReadBuffer();
  416.   modemStream->setTimeout(10000);
  417.   baudDetermined = true;
  418. }
  419.  
  420. void TheThingsNetwork::reset(bool adr)
  421. {
  422.   autoBaud();
  423.   readResponse(SYS_TABLE, SYS_RESET, buffer, sizeof(buffer));
  424.  
  425.   autoBaud();
  426.   readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VER, buffer, sizeof(buffer));
  427.  
  428.   // buffer contains "RN2xx3[xx] x.x.x ...", splitting model from version
  429.   char *model = strtok(buffer, " ");
  430.   debugPrintIndex(SHOW_MODEL, model);
  431.   char *version = strtok(NULL, " ");
  432.   debugPrintIndex(SHOW_VERSION, version);
  433.  
  434.   readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer));
  435.   sendMacSet(MAC_DEVEUI, buffer);
  436.   if (adr)
  437.   {
  438.     sendMacSet(MAC_ADR, "on");
  439.   }
  440.   else
  441.   {
  442.     sendMacSet(MAC_ADR, "off");
  443.   }
  444.   this->adr = adr;
  445.   this->needsHardReset = false;
  446. }
  447.  
  448. void TheThingsNetwork::resetHard(uint8_t resetPin){
  449.   digitalWrite(resetPin, LOW);
  450.   delay(1000);
  451.   digitalWrite(resetPin, HIGH);
  452. }
  453.  
  454. void TheThingsNetwork::saveState()
  455. {
  456.   debugPrint(SENDING);
  457.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  458.   sendCommand(MAC_TABLE, MAC_SAVE, false);
  459.   modemStream->write(SEND_MSG);
  460.   debugPrintLn();
  461.   waitForOk();
  462. }
  463.  
  464. void TheThingsNetwork::onMessage(void (*cb)(const uint8_t *payload, size_t size, port_t port))
  465. {
  466.   messageCallback = cb;
  467. }
  468.  
  469. bool TheThingsNetwork::personalize(const char *devAddr, const char *nwkSKey, const char *appSKey)
  470. {
  471.   reset(adr);
  472.   if (strlen(devAddr) != 8 || strlen(appSKey) != 32 || strlen(nwkSKey) != 32)
  473.   {
  474.     debugPrintMessage(ERR_MESSAGE, ERR_KEY_LENGTH);
  475.     return false;
  476.   }
  477.   sendMacSet(MAC_DEVADDR, devAddr);
  478.   sendMacSet(MAC_NWKSKEY, nwkSKey);
  479.   sendMacSet(MAC_APPSKEY, appSKey);
  480.   return personalize();
  481. }
  482.  
  483. bool TheThingsNetwork::personalize()
  484. {
  485.   configureChannels(fsb);
  486.   setSF(sf);
  487.   sendJoinSet(MAC_JOIN_MODE_ABP);
  488.   readLine(buffer, sizeof(buffer));
  489.   if (pgmstrcmp(buffer, CMP_ACCEPTED) != 0)
  490.   {
  491.     debugPrintMessage(ERR_MESSAGE, ERR_PERSONALIZE_NOT_ACCEPTED, buffer);
  492.     debugPrintMessage(ERR_MESSAGE, ERR_CHECK_CONFIGURATION);
  493.     return false;
  494.   }
  495.  
  496.   readResponse(MAC_TABLE, MAC_CH_TABLE, MAC_CHANNEL_STATUS, buffer, sizeof(buffer));
  497.   debugPrintMessage(SUCCESS_MESSAGE, SCS_PERSONALIZE_ACCEPTED, buffer);
  498.   return true;
  499. }
  500.  
  501. bool TheThingsNetwork::provision(const char *appEui, const char *appKey)
  502. {
  503.   reset(adr);
  504.   if (strlen(appEui) != 16 || strlen(appKey) != 32)
  505.   {
  506.     debugPrintMessage(ERR_MESSAGE, ERR_KEY_LENGTH);
  507.     return false;
  508.   }
  509.   readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer));
  510.   sendMacSet(MAC_DEVEUI, buffer);
  511.   sendMacSet(MAC_APPEUI, appEui);
  512.   sendMacSet(MAC_APPKEY, appKey);
  513.   saveState();
  514.   return true;
  515. }
  516.  
  517. bool TheThingsNetwork::join(int8_t retries, uint32_t retryDelay)
  518. {
  519.   int8_t attempts = 0;
  520.   configureChannels(fsb);
  521.   setSF(sf);
  522.   while (retries == -1 || attempts <= retries)
  523.   {
  524.     attempts++;
  525.     if (!sendJoinSet(MAC_JOIN_MODE_OTAA))
  526.     {
  527.       debugPrintMessage(ERR_MESSAGE, ERR_JOIN_FAILED);
  528.       delay(retryDelay);
  529.       continue;
  530.     }
  531.     readLine(buffer, sizeof(buffer));
  532.     if (pgmstrcmp(buffer, CMP_ACCEPTED) != 0)
  533.     {
  534.       debugPrintMessage(ERR_MESSAGE, ERR_JOIN_NOT_ACCEPTED, buffer);
  535.       debugPrintMessage(ERR_MESSAGE, ERR_CHECK_CONFIGURATION);
  536.       delay(retryDelay);
  537.       continue;
  538.     }
  539.     readResponse(MAC_TABLE, MAC_CH_TABLE, MAC_CHANNEL_STATUS, buffer, sizeof(buffer));
  540.     debugPrintMessage(SUCCESS_MESSAGE, SCS_JOIN_ACCEPTED, buffer);
  541.     readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DEVADDR, buffer, sizeof(buffer));
  542.     debugPrintIndex(SHOW_DEVADDR, buffer);
  543.     return true;
  544.   }
  545.   return false;
  546. }
  547.  
  548. bool TheThingsNetwork::join(const char *appEui, const char *appKey, int8_t retries, uint32_t retryDelay)
  549. {
  550.   return provision(appEui, appKey) && join(retries, retryDelay);
  551. }
  552.  
  553. ttn_response_t TheThingsNetwork::sendBytes(const uint8_t *payload, size_t length, port_t port, bool confirm, uint8_t sf)
  554. {
  555.   if (sf != 0)
  556.   {
  557.     setSF(sf);
  558.   }
  559.  
  560.   uint8_t mode = confirm ? MAC_TX_TYPE_CNF : MAC_TX_TYPE_UCNF;
  561.   if (!sendPayload(mode, port, (uint8_t *)payload, length))
  562.   {
  563.     debugPrintMessage(ERR_MESSAGE, ERR_SEND_COMMAND_FAILED);
  564.     return TTN_ERROR_SEND_COMMAND_FAILED;
  565.   }
  566.  
  567.   readLine(buffer, sizeof(buffer));
  568.  
  569.   if (pgmstrcmp(buffer, CMP_MAC_TX_OK) == 0)
  570.   {
  571.     debugPrintMessage(SUCCESS_MESSAGE, SCS_SUCCESSFUL_TRANSMISSION);
  572.     return TTN_SUCCESSFUL_TRANSMISSION;
  573.   }
  574.  
  575.   if (pgmstrcmp(buffer, CMP_MAC_RX) == 0)
  576.   {
  577.     port_t downlinkPort = receivedPort(buffer + 7);
  578.     char *data = buffer + 7 + digits(downlinkPort) + 1;
  579.     size_t downlinkLength = strlen(data) / 2;
  580.     if (downlinkLength > 0)
  581.     {
  582.       uint8_t downlink[downlinkLength];
  583.       for (size_t i = 0, d = 0; i < downlinkLength; i++, d += 2)
  584.       {
  585.         downlink[i] = TTN_HEX_PAIR_TO_BYTE(data[d], data[d + 1]);
  586.       }
  587.       debugPrintMessage(SUCCESS_MESSAGE, SCS_SUCCESSFUL_TRANSMISSION_RECEIVED, data);
  588.       if (messageCallback)
  589.       {
  590.         messageCallback(downlink, downlinkLength, downlinkPort);
  591.       }
  592.     }
  593.     else
  594.     {
  595.       debugPrintMessage(SUCCESS_MESSAGE, SCS_SUCCESSFUL_TRANSMISSION);
  596.     }
  597.     return TTN_SUCCESSFUL_RECEIVE;
  598.   }
  599.  
  600.   debugPrintMessage(ERR_MESSAGE, ERR_UNEXPECTED_RESPONSE, buffer);
  601.   return TTN_ERROR_UNEXPECTED_RESPONSE;
  602. }
  603.  
  604. ttn_response_t TheThingsNetwork::poll(port_t port, bool confirm)
  605. {
  606.   uint8_t payload[] = {0x00};
  607.   return sendBytes(payload, 1, port, confirm);
  608. }
  609.  
  610. void TheThingsNetwork::showStatus()
  611. {
  612.   readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer));
  613.   debugPrintIndex(SHOW_EUI, buffer);
  614.   readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer));
  615.   debugPrintIndex(SHOW_BATTERY, buffer);
  616.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, sizeof(buffer));
  617.   debugPrintIndex(SHOW_APPEUI, buffer);
  618.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DEVEUI, buffer, sizeof(buffer));
  619.   debugPrintIndex(SHOW_DEVEUI, buffer);
  620.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DR, buffer, sizeof(buffer));
  621.   debugPrintIndex(SHOW_DATA_RATE, buffer);
  622.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_RXDELAY1, buffer, sizeof(buffer));
  623.   debugPrintIndex(SHOW_RX_DELAY_1, buffer);
  624.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_RXDELAY2, buffer, sizeof(buffer));
  625.   debugPrintIndex(SHOW_RX_DELAY_2, buffer);
  626. }
  627.  
  628. void TheThingsNetwork::configureEU868()
  629. {
  630.   sendMacSet(MAC_RX2, "3 869525000");
  631.   sendChSet(MAC_CHANNEL_DRRANGE, 1, "0 6");
  632.  
  633.   char buf[10];
  634.   uint32_t freq = 867100000;
  635.   uint8_t ch;
  636.   for (ch = 0; ch < 8; ch++)
  637.   {
  638.     sendChSet(MAC_CHANNEL_DCYCLE, ch, "799");
  639.     if (ch > 2)
  640.     {
  641.       sprintf(buf, "%lu", freq);
  642.       sendChSet(MAC_CHANNEL_FREQ, ch, buf);
  643.       sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 5");
  644.       sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  645.       freq = freq + 200000;
  646.     }
  647.   }
  648.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_EU868);
  649. }
  650.  
  651. void TheThingsNetwork::configureUS915(uint8_t fsb)
  652. {
  653.   uint8_t ch;
  654.   uint8_t chLow = fsb > 0 ? (fsb - 1) * 8 : 0;
  655.   uint8_t chHigh = fsb > 0 ? chLow + 7 : 71;
  656.   uint8_t ch500 = fsb + 63;
  657.   for (ch = 0; ch < 72; ch++)
  658.   {
  659.     if (ch == ch500 || (ch <= chHigh && ch >= chLow))
  660.     {
  661.       sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  662.       if (ch < 63)
  663.       {
  664.         sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 3");
  665.       }
  666.     }
  667.     else
  668.     {
  669.       sendChSet(MAC_CHANNEL_STATUS, ch, "off");
  670.     }
  671.   }
  672.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_US915);
  673. }
  674.  
  675. void TheThingsNetwork::configureAU915(uint8_t fsb)
  676. {
  677.   uint8_t ch;
  678.   uint8_t chLow = fsb > 0 ? (fsb - 1) * 8 : 0;
  679.   uint8_t chHigh = fsb > 0 ? chLow + 7 : 71;
  680.   uint8_t ch500 = fsb + 63;
  681.   for (ch = 0; ch < 72; ch++)
  682.   {
  683.     if (ch == ch500 || (ch <= chHigh && ch >= chLow))
  684.     {
  685.       sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  686.       if (ch < 63)
  687.       {
  688.         sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 3");
  689.       }
  690.     }
  691.     else
  692.     {
  693.       sendChSet(MAC_CHANNEL_STATUS, ch, "off");
  694.     }
  695.   }
  696.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_AU915);
  697. }
  698.  
  699. void TheThingsNetwork::configureAS920_923()
  700. {
  701.   /* RN2903AS 1.0.3rc9 defaults
  702.    * CH0 = 923.2MHz
  703.    * CH1 = 923.4MHz
  704.    */
  705.   sendMacSet(MAC_ADR, "off"); // TODO: remove when ADR is implemented for this plan
  706.   sendMacSet(MAC_RX2, "2 923200000");
  707.  
  708.   char buf[10];
  709.   uint32_t freq = 922000000;
  710.   uint8_t ch;
  711.   for (ch = 0; ch < 8; ch++)
  712.   {
  713.     sendChSet(MAC_CHANNEL_DCYCLE, ch, "799");
  714.     if (ch > 1)
  715.     {
  716.       sprintf(buf, "%lu", freq);
  717.       sendChSet(MAC_CHANNEL_FREQ, ch, buf);
  718.       sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 5");
  719.       sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  720.       freq = freq + 200000;
  721.     }
  722.   }
  723.   // TODO: SF7BW250/DR6 channel, not properly supported by RN2903AS yet
  724.   //sendChSet(MAC_CHANNEL_DCYCLE, 8, "799");
  725.   //sendChSet(MAC_CHANNEL_FREQ, 8, "922100000");
  726.   //sendChSet(MAC_CHANNEL_DRRANGE, 8, "6 6");
  727.   //sendChSet(MAC_CHANNEL_STATUS, 8, "on");
  728.   // TODO: Add FSK channel on 921800000
  729.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_AS920_923);
  730. }
  731.  
  732. void TheThingsNetwork::configureAS923_925()
  733. {
  734.   /* RN2903AS 1.0.3rc9 defaults
  735.    * CH0 = 923.2MHz
  736.    * CH1 = 923.4MHz
  737.    */
  738.   sendMacSet(MAC_ADR, "off"); // TODO: remove when ADR is implemented for this plan
  739.   sendMacSet(MAC_RX2, "2 923200000");
  740.  
  741.   char buf[10];
  742.   uint32_t freq = 923600000;
  743.   uint8_t ch;
  744.   for (ch = 0; ch < 8; ch++)
  745.   {
  746.     sendChSet(MAC_CHANNEL_DCYCLE, ch, "799");
  747.     if (ch > 1)
  748.     {
  749.       sprintf(buf, "%lu", freq);
  750.       sendChSet(MAC_CHANNEL_FREQ, ch, buf);
  751.       sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 5");
  752.       sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  753.       freq = freq + 200000;
  754.     }
  755.   }
  756.   // TODO: SF7BW250/DR6 channel, not properly supported by RN2903AS yet
  757.   //sendChSet(MAC_CHANNEL_DCYCLE, 8, "799");
  758.   //sendChSet(MAC_CHANNEL_FREQ, 8, "924500000");
  759.   //sendChSet(MAC_CHANNEL_DRRANGE, 8, "6 6");
  760.   //sendChSet(MAC_CHANNEL_STATUS, 8, "on");
  761.   // TODO: Add FSK channel on 924800000
  762.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_AS923_925);
  763. }
  764.  
  765. void TheThingsNetwork::configureKR920_923()
  766. {
  767.   sendMacSet(MAC_ADR, "off"); // TODO: remove when ADR is implemented for this plan
  768.   sendMacSet(MAC_RX2, "0 921900000"); // KR still uses SF12 for now. Might change to SF9 later.
  769.  
  770.   //disable two default LoRaWAN channels
  771.   sendChSet(MAC_CHANNEL_STATUS, 0, "off");
  772.   sendChSet(MAC_CHANNEL_STATUS, 1, "off");
  773.  
  774.   char buf[10];
  775.   uint32_t freq = 922100000;
  776.   uint8_t ch;
  777.   for (ch = 2; ch < 9; ch++)
  778.   {
  779.     sendChSet(MAC_CHANNEL_DCYCLE, ch, "799");
  780.     sprintf(buf, "%lu", freq);
  781.     sendChSet(MAC_CHANNEL_FREQ, ch, buf);
  782.     sendChSet(MAC_CHANNEL_DRRANGE, ch, "0 5");
  783.     sendChSet(MAC_CHANNEL_STATUS, ch, "on");
  784.     freq = freq + 200000;
  785.   }
  786.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_KR920_923);
  787. }
  788.  
  789. void TheThingsNetwork::configureIN865_867()
  790. {
  791.   sendMacSet(MAC_ADR, "off"); // TODO: remove when ADR is implemented for this plan
  792.   sendMacSet(MAC_RX2, "2 866550000"); // SF10
  793.  
  794.   // Disable the three default LoRaWAN channels
  795.   sendChSet(MAC_CHANNEL_STATUS, 0, "off");
  796.   sendChSet(MAC_CHANNEL_STATUS, 1, "off");
  797.   sendChSet(MAC_CHANNEL_STATUS, 2, "off");
  798.  
  799.   // Channel 3
  800.   sendChSet(MAC_CHANNEL_DCYCLE, 3, "299");
  801.   sendChSet(MAC_CHANNEL_FREQ, 3, "865062500");
  802.   sendChSet(MAC_CHANNEL_DRRANGE, 3, "0 5");
  803.   sendChSet(MAC_CHANNEL_STATUS, 3, "on");
  804.  
  805.   // Channel 4
  806.   sendChSet(MAC_CHANNEL_DCYCLE, 4, "299");
  807.   sendChSet(MAC_CHANNEL_FREQ, 4, "865402500");
  808.   sendChSet(MAC_CHANNEL_DRRANGE, 4, "0 5");
  809.   sendChSet(MAC_CHANNEL_STATUS, 4, "on");
  810.  
  811.   // Channel 5
  812.   sendChSet(MAC_CHANNEL_DCYCLE, 5, "299");
  813.   sendChSet(MAC_CHANNEL_FREQ, 5, "865985000");
  814.   sendChSet(MAC_CHANNEL_DRRANGE, 5, "0 5");
  815.   sendChSet(MAC_CHANNEL_STATUS, 5, "on");
  816.  
  817.   sendMacSet(MAC_PWRIDX, TTN_PWRIDX_IN865_867);
  818. }
  819.  
  820. void TheThingsNetwork::configureChannels(uint8_t fsb)
  821. {
  822.   switch (fp)
  823.   {
  824.   case TTN_FP_EU868:
  825.     configureEU868();
  826.     break;
  827.   case TTN_FP_US915:
  828.     configureUS915(fsb);
  829.     break;
  830.   case TTN_FP_AU915:
  831.     configureAU915(fsb);
  832.     break;
  833.   case TTN_FP_AS920_923:
  834.     configureAS920_923();
  835.     break;
  836.   case TTN_FP_AS923_925:
  837.     configureAS923_925();
  838.     break;
  839.   case TTN_FP_KR920_923:
  840.     configureKR920_923();
  841.     break;
  842.   case TTN_FP_IN865_867:
  843.     configureIN865_867();
  844.     break;
  845.   default:
  846.     debugPrintMessage(ERR_MESSAGE, ERR_INVALID_FP);
  847.     break;
  848.   }
  849.   sendMacSet(MAC_RETX, TTN_RETX);
  850. }
  851.  
  852. bool TheThingsNetwork::setSF(uint8_t sf)
  853. {
  854.   uint8_t dr;
  855.   switch (fp)
  856.   {
  857.   case TTN_FP_EU868:
  858.   case TTN_FP_IN865_867:
  859.   case TTN_FP_AS920_923:
  860.   case TTN_FP_AS923_925:
  861.   case TTN_FP_KR920_923:
  862.     dr = 12 - sf;
  863.     break;
  864.   case TTN_FP_US915:
  865.   case TTN_FP_AU915:
  866.     dr = 10 - sf;
  867.     break;
  868.   }
  869.   char s[2];
  870.   s[0] = '0' + dr;
  871.   s[1] = '\0';
  872.   return sendMacSet(MAC_DR, s);
  873. }
  874.  
  875. void TheThingsNetwork::sendCommand(uint8_t table, uint8_t index, bool appendSpace, bool print)
  876. {
  877.   char command[100];
  878.   switch (table)
  879.   {
  880.   case MAC_TABLE:
  881.     strcpy(command, mac_table[index]);
  882.     break;
  883.   case MAC_GET_SET_TABLE:
  884.     strcpy(command, mac_options[index]);
  885.     break;
  886.   case MAC_JOIN_TABLE:
  887.     strcpy(command, mac_join_mode[index]);
  888.     break;
  889.   case MAC_CH_TABLE:
  890.     strcpy(command, mac_ch_options[index]);
  891.     break;
  892.   case MAC_TX_TABLE:
  893.     strcpy(command, mac_tx_table[index]);
  894.     break;
  895.   case SYS_TABLE:
  896.     strcpy(command, sys_table[index]);
  897.     break;
  898.   case RADIO_TABLE:
  899.     strcpy(command, radio_table[index]);
  900.     break;
  901.   default:
  902.     return;
  903.   }
  904.   modemStream->write(command);
  905.   if (appendSpace)
  906.   {
  907.     modemStream->write(" ");
  908.   }
  909.   if (print)
  910.   {
  911.     debugPrint(command);
  912.     debugPrint(" ");
  913.   }
  914. }
  915.  
  916. bool TheThingsNetwork::sendMacSet(uint8_t index, const char *value)
  917. {
  918.   clearReadBuffer();
  919.   debugPrint(SENDING);
  920.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  921.   sendCommand(MAC_TABLE, MAC_SET, true);
  922.   sendCommand(MAC_GET_SET_TABLE, index, true);
  923.   modemStream->write(value);
  924.   modemStream->write(SEND_MSG);
  925.   debugPrintLn(value);
  926.   return waitForOk();
  927. }
  928.  
  929. bool TheThingsNetwork::waitForOk()
  930. {
  931.   readLine(buffer, sizeof(buffer));
  932.   if (pgmstrcmp(buffer, CMP_OK) != 0)
  933.   {
  934.     debugPrintMessage(ERR_MESSAGE, ERR_RESPONSE_IS_NOT_OK, buffer);
  935.     return false;
  936.   }
  937.   return true;
  938. }
  939.  
  940. bool TheThingsNetwork::sendChSet(uint8_t index, uint8_t channel, const char *value)
  941. {
  942.   clearReadBuffer();
  943.   char ch[5];
  944.   if (channel > 9)
  945.   {
  946.     ch[0] = ((channel - (channel % 10)) / 10) + 48;
  947.     ch[1] = (channel % 10) + 48;
  948.     ch[2] = '\0';
  949.   }
  950.   else
  951.   {
  952.     ch[0] = channel + 48;
  953.     ch[1] = '\0';
  954.   }
  955.   debugPrint(SENDING);
  956.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  957.   sendCommand(MAC_TABLE, MAC_SET, true);
  958.   sendCommand(MAC_GET_SET_TABLE, MAC_CH, true);
  959.   sendCommand(MAC_CH_TABLE, index, true);
  960.   modemStream->write(ch);
  961.   modemStream->write(" ");
  962.   modemStream->write(value);
  963.   modemStream->write(SEND_MSG);
  964.   debugPrint(channel);
  965.   debugPrint(" ");
  966.   debugPrintLn(value);
  967.   return waitForOk();
  968. }
  969.  
  970. bool TheThingsNetwork::sendJoinSet(uint8_t type)
  971. {
  972.   clearReadBuffer();
  973.   debugPrint(SENDING);
  974.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  975.   sendCommand(MAC_TABLE, MAC_JOIN, true);
  976.   sendCommand(MAC_JOIN_TABLE, type, false);
  977.   modemStream->write(SEND_MSG);
  978.   debugPrintLn();
  979.   return waitForOk();
  980. }
  981.  
  982. bool TheThingsNetwork::sendPayload(uint8_t mode, uint8_t port, uint8_t *payload, size_t length)
  983. {
  984.   clearReadBuffer();
  985.   debugPrint(SENDING);
  986.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  987.   sendCommand(MAC_TABLE, MAC_TX, true);
  988.   sendCommand(MAC_TX_TABLE, mode, true);
  989.   char sport[4];
  990.   if (port > 99)
  991.   {
  992.     sport[0] = ((port - (port % 100)) / 100) + 48;
  993.     sport[1] = (((port % 100) - (port % 10)) / 10) + 48;
  994.     sport[2] = (port % 10) + 48;
  995.     sport[3] = '\0';
  996.   }
  997.   else if (port > 9)
  998.   {
  999.     sport[0] = ((port - (port % 10)) / 10) + 48;
  1000.     sport[1] = (port % 10) + 48;
  1001.     sport[2] = '\0';
  1002.   }
  1003.   else
  1004.   {
  1005.     sport[0] = port + 48;
  1006.     sport[1] = '\0';
  1007.   }
  1008.   modemStream->write(sport);
  1009.   modemStream->print(" ");
  1010.   debugPrint(sport);
  1011.   debugPrint(" ");
  1012.   uint8_t i = 0;
  1013.   for (i = 0; i < length; i++)
  1014.   {
  1015.     if (payload[i] < 16)
  1016.     {
  1017.       modemStream->print("0");
  1018.       modemStream->print(payload[i], HEX);
  1019.       debugPrint("0");
  1020.       debugPrint(payload[i], HEX);
  1021.     }
  1022.     else
  1023.     {
  1024.       modemStream->print(payload[i], HEX);
  1025.       debugPrint(payload[i], HEX);
  1026.     }
  1027.   }
  1028.   modemStream->write(SEND_MSG);
  1029.   debugPrintLn();
  1030.   return waitForOk();
  1031. }
  1032.  
  1033. void TheThingsNetwork::sleep(uint32_t mseconds)
  1034. {
  1035.   if (mseconds < 100)
  1036.   {
  1037.     return;
  1038.   }
  1039.  
  1040.   debugPrint(SENDING);
  1041.   sendCommand(SYS_TABLE, SYS_PREFIX, true);
  1042.   sendCommand(SYS_TABLE, SYS_SLEEP, true);
  1043.  
  1044.   sprintf(buffer, "%lu", mseconds);
  1045.   modemStream->write(buffer);
  1046.   modemStream->write(SEND_MSG);
  1047.   debugPrintLn(buffer);
  1048. }
  1049.  
  1050. void TheThingsNetwork::wake()
  1051. {
  1052.   autoBaud();
  1053. }
  1054.  
  1055. void TheThingsNetwork::linkCheck(uint16_t seconds)
  1056. {
  1057.   clearReadBuffer();
  1058.   debugPrint(SENDING);
  1059.   sendCommand(MAC_TABLE, MAC_PREFIX, true);
  1060.   sendCommand(MAC_TABLE, MAC_SET, true);
  1061.   sendCommand(MAC_GET_SET_TABLE, MAC_LINKCHK, true);
  1062.  
  1063.   sprintf(buffer, "%u", seconds);
  1064.   modemStream->write(buffer);
  1065.   modemStream->write(SEND_MSG);
  1066.   debugPrintLn(buffer);
  1067.   waitForOk();
  1068. }
  1069.  
  1070. uint8_t TheThingsNetwork::getLinkCheckGateways()
  1071. {
  1072.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_GWNB, buffer, sizeof(buffer));
  1073.   return strtol(buffer, NULL, 10);
  1074. }
  1075.  
  1076. uint8_t TheThingsNetwork::getLinkCheckMargin()
  1077. {
  1078.   readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_MRGN, buffer, sizeof(buffer));
  1079.   return strtol(buffer, NULL, 10);
  1080. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement