Advertisement
Guest User

Untitled

a guest
Jan 27th, 2020
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.57 KB | None | 0 0
  1. #include <SPI.h>
  2. #include <RH_RF95.h>
  3. #include <Process.h>
  4. #include <EEPROM.h>
  5. #include <FileIO.h>
  6. #include <Console.h>
  7.  
  8. // Comment to disable verbose debugging.
  9. #define DEBUG_VERBOSE
  10.  
  11. // Comment to disable encryption.
  12. //#define ENCRYPT_ENABLE
  13.  
  14. // Comment to disable the LED.
  15. #define LED_ENABLE
  16.  
  17. #ifdef LED_ENABLE
  18.     // Define pin of the LED.
  19.     #define LED_PIN A2
  20. #endif
  21.  
  22. // Define the LoRa RF95_FREQ use for this client.
  23. #define RFM95_RST 9
  24. #define RF95_FREQ 868.00
  25. #define RFM95_BAND 500000
  26. #define RFM95_SPREAD 12
  27.  
  28. // Gateway ID
  29. #define ID_GATEWAY 15
  30.  
  31. // Gateway ID address in EEPROM.
  32. //#define ID_ADDRESS 0x00
  33.  
  34. // Max clients to support, more clients will increase time to establish network and polling.
  35. #define MAX_CLIENT 3
  36.  
  37. // Time to refresh the network. Will add new clients after network refresh.
  38. #define REFRESH_TIME 30000
  39.  
  40. // The no response retry count before it stops the broadcast message and finishes network setup.
  41. #define MAX_BROADCAST_RETRY 15
  42.  
  43. // How many retries after which to kick a client if there is no response.
  44. #define MAX_REMOVE_RETRY 5
  45.  
  46. #ifdef ENCRYPT_ENABLE
  47.     #include "encrypt.h"
  48.     ENCRYPT  encrypt_decrypt;
  49.  
  50.     // Define the encrypt key, so different group of LoRa devices won't communicate with each other.
  51.     unsigned char encryptkey[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
  52. #endif
  53.  
  54.  
  55. RH_RF95 rf95;
  56.  
  57. String sensor_data = "Start";
  58.  
  59. int gateway_id = 0;
  60.  
  61. int network_setup_finish = 0 ; // Whether network has finished setting up.
  62. int network_loop_count = 2;
  63. int b = 0; // Network set up counter
  64.  
  65. char clients[MAX_CLIENT] = {0}; // Client ID array
  66. int client_numbers = 0;// Client count
  67. int broadcast_retry = 0 ; // Broadcast retry counter
  68. int no_response_count = 0; // Counter for no response from client
  69.  
  70. long poll_start_time = 0;
  71. long total_poll_time = 0;
  72.  
  73. int CrcFlag = 0;
  74.  
  75.  
  76.  
  77. void setup() {
  78.     manualReset();
  79.  
  80.     Bridge.begin(115200);
  81.     Console.begin();
  82.     delay(100);
  83.  
  84.     while (!Console)
  85.         delay(1);    
  86.     Console.print("Bridge ready!\n");
  87.  
  88.     delay(100);
  89.     setupRadio();
  90.     #ifdef LED_ENABLE
  91.         pinMode(LED_PIN, OUTPUT);
  92.     #endif
  93.     store_data_linux(true); // Store the data on Linux
  94. }
  95.  
  96. uint16_t calcByte(uint16_t crc, uint8_t b) {
  97.     uint32_t i = 0;
  98.     crc = crc ^ (uint32_t)b << 8;
  99.  
  100.     for (i = 0; i < 8; i++) {
  101.         if ((crc & 0x8000) == 0x8000)
  102.             crc = crc << 1 ^ 0x1021;
  103.         else
  104.             crc = crc << 1;
  105.     }
  106.     return crc & 0xffff;
  107. }
  108.  
  109. uint16_t CRC16(uint8_t *pBuffer, uint32_t length) {
  110.     uint16_t wCRC16 = 0;
  111.     uint32_t i = 0;
  112.  
  113.     if ((pBuffer == 0) || (length == 0))
  114.         return 0;
  115.  
  116.     for (i = 0; i < length; i++)
  117.         wCRC16 = calcByte(wCRC16, pBuffer[i]);
  118.  
  119.     return wCRC16;
  120. }
  121.  
  122. uint16_t recdata(unsigned char* recbuf, int Length) {
  123.     uint16_t crcdata = 0;
  124.     uint16_t recCRCData = 0;
  125.    
  126.     crcdata = CRC16(recbuf, Length - 2); // Calculate the CRC for the received message
  127.     recCRCData = recbuf[Length - 1]; // Get the CRC high byte
  128.     recCRCData = recCRCData << 8; // Get the CRC low byte
  129.     recCRCData |= recbuf[Length - 2]; // Get the receive CRC
  130.  
  131.     if (crcdata == recCRCData) {
  132.         CrcFlag = 1;
  133.         crcdata = 0;
  134.         recCRCData = 0;
  135.         #ifdef DEBUG_VERBOSE
  136.             Console.println("CRC++++");
  137.         #endif
  138.     }
  139.     else {
  140.         CrcFlag = 0 ;
  141.         crcdata = 0;
  142.         recCRCData = 0;
  143.     }
  144. }
  145.  
  146. void set_up_network(void) {
  147.     uint8_t broadcast[4] = {0}; // Broadcast Message
  148.     broadcast[0] = 'B';
  149.     broadcast[1] = 'C';
  150.     broadcast[2] = ':';
  151.     broadcast[3] = gateway_id;
  152.     int length = sizeof(broadcast); // Get broadcast message length
  153.  
  154.     #ifdef ENCRYPT_ENABLE
  155.         encrypt_decrypt.btea(broadcast, length, encryptkey); // Encrypt the broadcast message
  156.     #endif
  157.     for (b = 0; b < network_loop_count; b++) { // Loop to set up network
  158.         #ifdef DEBUG_VERBOSE
  159.             Console.println("Send broadcast message");
  160.         #endif
  161.         rf95.send(broadcast , sizeof(broadcast));
  162.         rf95.waitPacketSent();
  163.         #ifdef DEBUG_VERBOSE
  164.             Console.println("Packet sent");
  165.         #endif
  166.  
  167.         if (rf95.waitAvailableTimeout(1000)) { // Check the incoming message
  168.             Console.println("Get an incoming message");
  169.             uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
  170.             uint8_t len = sizeof(buf);
  171.             if (rf95.recv(buf, &len)) {
  172.                 #ifdef ENCRYPT_ENABLE
  173.                     encrypt_decrypt.btea(buf, -len, encryptkey); // Decode the message
  174.                 #endif
  175.  
  176.                 /*------JOIN REQUEST-------*/
  177.  
  178.                 if (buf[0] == 'J' && buf[1] == 'R' && buf[2] == ':') { // Get a join request, store the client ID
  179.                     #ifdef DEBUG_VERBOSE
  180.                         Console.println(buf[0]);
  181.                         Console.println(buf[1]);
  182.                         Console.println(buf[2]);
  183.                         Console.println(buf[3]);
  184.                     #endif
  185.  
  186.                     if (buf[3] == 0) { // Error Message
  187.                         Console.println("SET_UP_NETWORK: Error Message");
  188.                     }
  189.                     else {
  190.                         for (int b = 0; b < 3; b++) { // Send 3 Join ACK to the client, make sure it arrives
  191.  
  192.                             /*------JOIN ACCEPT-------*/
  193.  
  194.                             uint8_t JoinAck[4] = {0}; // Join ACK message
  195.                             JoinAck[0] = 'J';
  196.                             JoinAck[1] = 'A';
  197.                             JoinAck[2] = ':';
  198.                             JoinAck[3] = buf[3]; // Put client ID
  199.                             Console.println("SET_UP_NETWORK: Sending Join Accept: ");
  200.  
  201.                             int length = sizeof(JoinAck); // Get data length
  202.                             #ifdef ENCRYPT_ENABLE
  203.                                 encrypt_decrypt.btea(JoinAck, length, encryptkey); // Encode
  204.                             #endif
  205.                             Console.print("Send Join ACK to client:");
  206.                             Console.println(buf[3]);
  207.                             rf95.send(JoinAck, sizeof(JoinAck));
  208.                             rf95.waitPacketSent();
  209.                             broadcast_retry = 0;
  210.                             delay(500);
  211.                         }
  212.                         int pos ;
  213.                         for (pos = 0; pos < sizeof(clients); pos++) { // Check if this client is already stored
  214.                             if (clients[pos] == buf[3]) {
  215.                                 Console.println("SET_UP_NETWORK: Client already registered: " + buf[3]);
  216.                                 break;
  217.                             }
  218.                         }
  219.                         if (pos == sizeof(clients)) {
  220.                             Console.println("SET_UP_NETWORK: Registering Client: " + buf[3]);
  221.  
  222.                             clients[client_numbers] = buf[3]; // Store the client id
  223.                             client_numbers++;
  224.                             broadcast_retry = 0; // Get a new client, reset retry count
  225.                         }
  226.                     }
  227.                 }
  228.                 else {
  229.                     Console.println("SET_UP_NETWORK: Join Request Message Error");
  230.                 }
  231.             }
  232.         }
  233.         else {
  234.             broadcast_retry++;
  235.             #ifdef DEBUG_VERBOSE
  236.                 Console.println("SET_UP_NETWORK: Broadcast retry");
  237.             #endif
  238.  
  239.             if (broadcast_retry > MAX_BROADCAST_RETRY) { // Check if retry count exceed the max retry, if yes, network set up done
  240.                 network_setup_finish = 1;
  241.                 broadcast_retry = 0;
  242.                 break;
  243.             }
  244.         }
  245.     }
  246.     delay(100);
  247. }
  248.  
  249. void polling_clients(void) {
  250.     int polling_count = 0;
  251.     poll_start_time = millis();
  252.  
  253.     for (polling_count = 0; polling_count < 2; polling_count++) { // Send data requst to every client one by one
  254.         uint8_t query[4] = {0}; // Data request message
  255.         query[3] = clients[polling_count];
  256.         for (int poll_cnt = 0; poll_cnt < MAX_REMOVE_RETRY; poll_cnt++) { // Send a data requst message
  257.  
  258.             /*------DATA REQUEST SEND---------*/
  259.  
  260.             uint8_t query[4] = {0}; // Data request message
  261.             query[0] = 'D';
  262.             query[1] = 'R';
  263.             query[2] = ':';
  264.             query[3] = clients[polling_count] ; // Client ID to be polled
  265.  
  266.             #ifdef DEBUG_VERBOSE
  267.                 Console.print("POLLING -> Request Data from client: ");
  268.                 Console.print(query[3]);
  269.                 Console.print(" ;count: ");
  270.                 Console.println(poll_cnt);
  271.             #endif
  272.  
  273.             int length = sizeof(query); // Get length
  274.             #ifdef ENCRYPT_ENABLE
  275.                 encrypt_decrypt.btea(query, length, encryptkey); // Encode
  276.             #endif
  277.             rf95.send(query, sizeof(query)); // Send poll message
  278.             rf95.waitPacketSent();
  279.  
  280.             /*------DATA REQUEST RECEIVE---------*/
  281.            
  282.             if (rf95.waitAvailableTimeout(3000)) {
  283.                 Console.println("POLLING -> Get incoming message");
  284.                 uint8_t buf[RH_RF95_MAX_MESSAGE_LEN] = {0};
  285.                 uint8_t len = sizeof(buf);
  286.                 if (rf95.recv(buf, &len)) {
  287.                     no_response_count = 0;
  288.                     #ifdef ENCRYPT_ENABLE
  289.                         encrypt_decrypt.btea(buf, - len, encryptkey); // Decode incoming message
  290.                     #endif
  291.                     recdata(buf, len); // Calculate CRC
  292.                     sensor_data = "";
  293.                     for (int a = 0; a < len - 2; a++) // Store data
  294.                         if (a == 3 || a == 5)
  295.                             sensor_data += buf[a];
  296.                         else
  297.                             sensor_data += (char)buf[a];
  298.  
  299.                     #ifdef LED_ENABLE
  300.                         digitalWrite(LED_PIN, HIGH);
  301.                     #endif
  302.  
  303.                     no_response_count = 0;
  304.                     if (CrcFlag == 1) { // CRC calculation successful, match
  305.                         #ifdef DEBUG_VERBOSE
  306.                             Console.println("POLLING -> CRC succesful");
  307.                         #endif
  308.                         Console.print("POLLING -> Received data: ");
  309.                         Console.println(sensor_data);
  310.                         store_data_linux(false); // Store the data on Linux
  311.  
  312.                         #ifdef LED_ENABLE
  313.                             digitalWrite(LED_PIN, LOW);
  314.                         #endif
  315.  
  316.                         CrcFlag = 0;
  317.                         if (buf[0] == 'D' && buf[1] == 'S' && buf[3] == query[3]) {
  318.                             Console.print("POLLING -> Received data: ");
  319.                             Console.println(sensor_data);
  320.                             store_data_linux(false); // Store the data on Linux
  321.                             no_response_count = 0;
  322.  
  323.                             break;
  324.                         }
  325.                         else {
  326.                             no_response_count ++;
  327.                         }
  328.                     }
  329.                     else {
  330.                         Console.println("CRC Error");
  331.  
  332.                         #ifdef LED_ENABLE
  333.                             digitalWrite(LED_PIN, LOW);
  334.                         #endif
  335.                     }
  336.                 }
  337.             }
  338.             else {
  339.                 no_response_count ++;
  340.                 if (no_response_count == MAX_REMOVE_RETRY) { // No response from client, remove it after max retry
  341.                     no_response_count = 0;
  342.                     clients[polling_count] = 0;
  343.                     Console.print("Client ID:");
  344.                     Console.println(clients[polling_count]);
  345.                 }
  346.             }
  347.         }
  348.     }
  349.     total_poll_time += millis() - poll_start_time; // Get total poll time
  350.     Console.println(total_poll_time);
  351.     if (total_poll_time > REFRESH_TIME) { // Refresh the network
  352.         Console.println("Refresh network after timeout");
  353.         network_setup_finish = 0;
  354.         total_poll_time = 0;
  355.     }
  356. }
  357.  
  358. void loop() {
  359.     #ifdef DEBUG_VERBOSE
  360.         Console.println("Start concurrent client: ");
  361.         #ifdef ENCRYPT_ENABLE
  362.             Console.print("Encrypt encryptkey :");
  363.             Console.println((char*)encryptkey);
  364.         #endif
  365.         Console.print("Frequency :");
  366.         Console.println(RF95_FREQ);
  367.         Console.print("Gateway ID :");
  368.         Console.println(gateway_id);
  369.     #endif
  370.     if (network_setup_finish == 0) {
  371.         Console.println("Network setup...");
  372.         set_up_network(); // Set up the network
  373.     }
  374.     else {
  375.         Console.println("Polling...");
  376.         polling_clients(); // Request data from clients
  377.     }
  378. }
  379.  
  380. void store_data_linux(bool first) {
  381.     Console.print("Writing data...");
  382.  
  383.     /*
  384.     File script = FileSystem.open("/root/sensor_data/test.sh", FILE_WRITE);
  385.     // Shell script header
  386.     script.print("#!/bin/sh\n");
  387.     // Make the script executable
  388.     Process chmod;
  389.     chmod.begin("chmod");      // chmod: change mode
  390.     chmod.addParameter("+x");  // x stays for executable
  391.     chmod.addParameter("/root/sensor_data/test.sh");  // path to the file to make it executable
  392.     chmod.run();
  393.  
  394.     //  Process p;   // Create a process and call it "p"
  395.     //  p.begin("/root/sensor_data"); // Store data in Linux file /root/test.sh
  396.     //  p.addParameter(sensor_data); // add the data
  397.     //  Console.println("Writing to file.");
  398.     //
  399.     //  p.run();    // Run the process and wait for its termination
  400.     */
  401.  
  402.     File data = FileSystem.open("/var/iot/data", (first)?FILE_WRITE:FILE_APPEND);
  403.     data.println(sensor_data);
  404.     data.close();
  405.  
  406.     Console.print(" Done.\n");
  407. }
  408.  
  409. void setupRadio() {
  410.     while (!rf95.init()) {
  411.         Console.println("LoRa radio init failed");
  412.         Console.println("Uncomment '#define Console_DEBUG' in RH_RF95.cpp for detailed debug info");
  413.         while (1);
  414.     }
  415.     Console.println("LoRa radio init OK!");
  416.     if (!rf95.setFrequency(RF95_FREQ)) {
  417.         Console.println("setFrequency failed");
  418.         while (1);
  419.     }
  420.     rf95.setTxPower(13, false);
  421.     rf95.setSignalBandwidth(RFM95_BAND);
  422.     rf95.setSpreadingFactor(RFM95_SPREAD);
  423.     gateway_id = ID_GATEWAY;
  424.     //gateway_id = EEPROM.read(ID_ADDRESS); // Get gateway ID
  425.     FileSystem.begin();
  426. }
  427.  
  428. void manualReset() {
  429.     pinMode(RFM95_RST, OUTPUT);
  430.     delay(10);
  431.     digitalWrite(RFM95_RST, HIGH);
  432.     delay(10);
  433. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement