Gateway by Jorge Troncoso

Dependencies:   libmDot-mbed5

main.cpp

Committer:
jortronm2
Date:
2018-06-13
Revision:
0:e671110e33a3

File content as of revision 0:e671110e33a3:

#include "board_config.h"
#include "dot_util.h"
#include "mbed.h"
#include "RadioEvent.h"
#include "serialize.h"
#include "status_led.h"


#define ESP_UART_BAUD 115200
DigitalOut status_led_external(PIN_OUTPUT_LED_EXTERNAL);

void esp_wait_for_reply(float timeout);
int8_t esp_wait_for_response(float timeout, char *response);
int8_t esp_get_ip_status(float timeout, uint8_t *ip_status);


DigitalIn button(PIN_INPUT_BUTTON);
DigitalOut esp_reset(PIN_OUTPUT_ESP_POWER);
Serial debug_serial(PIN_OUTPUT_DEBUG_UART_TX, PIN_OUTPUT_DEBUG_UART_RX, DEBUG_UART_BAUD);
Serial esp_serial(PIN_OUTPUT_ESP_UART_TX, PIN_OUTPUT_ESP_UART_RX, ESP_UART_BAUD);
Timer timer;


// Radio settings.
uint8_t  radio_network_address[]     = {0x65, 0x34, 0x03, 0x04};
uint8_t  radio_network_session_key[] = {0x23, 0x45, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
uint8_t  radio_data_session_key[]    = {0xF0, 0x34, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};





// WiFi settings.
char *esp_wifi_network_ssid     = "TrelleborgNet";
char *esp_wifi_network_password = "TrelleborgNet";

//char *esp_wifi_network_ssid     = "Jorges iPhone";
//char *esp_wifi_network_password = "jorge123";

//char *esp_wifi_network_ssid     = "fatpoo";
//char *esp_wifi_network_password = "fatpoo123";


/*    Netherlands JTRON1
char *esp_wifi_network_ssid     = "Dirk Jan van Waardhuizen";
char *esp_wifi_network_password = "bl9ffvrk8qfi";
char *esp_thingspeak_api_key_1  = "07NREQD3ZCJU4VBD"; //JTRON1A_EUR
char *esp_thingspeak_api_key_2  = "9ZNZJFYPH7TA2GWH"; //JTRON1B_EUR
https://thingspeak.com/channels/305477
https://thingspeak.com/channels/325738
https://freeboard.io/board/VkEXvR
*/

/*    Singapore JTRON2
char *esp_wifi_network_ssid     = "JP 6S";
char *esp_wifi_network_password = "jp123456";
char *esp_thingspeak_api_key_1  = "I6ZBMOGDOULI20QA"; //JTRON2A_Aus
char *esp_thingspeak_api_key_2  = "QNUMBZ6VS5HSIGFD"; //JTRON2B_Aus
https://thingspeak.com/channels/329688
https://thingspeak.com/channels/329689
https://freeboard.io/board/_2lcKY
*/


/*    China Jerry JTRON3
char *esp_wifi_network_ssid     = "iPhone(2)";
char *esp_wifi_network_password = "Zhengzihang2008";
char *esp_thingspeak_api_key_1  = "F5QU9DKAPWQFTJP4"; //JTRON3A_EUR         
char *esp_thingspeak_api_key_2  = "DY0I2SI08XAFFWPX"; //JTRON3B_EUR
https://thingspeak.com/channels/347705
https://thingspeak.com/channels/347707
https://freeboard.io/board/7pAdKY
*/

/*    USA Tom JTRON4
char *esp_wifi_network_ssid     = "TrellIOTU";
char *esp_wifi_network_password = "WtLnVDOKh1";
char *esp_thingspeak_api_key_1  = "UW5IRWSEY1305S8T"; //JTRON4A_Aus
char *esp_thingspeak_api_key_2  = "89GAX32G1VUNY492"; //JTRON4B_Aus
https://thingspeak.com/channels/348224
https://freeboard.io/board/8YrieZ 
*/

    /*UK David JTRON5
char *esp_wifi_network_ssid     = "Dave’s iPhone";
char *esp_wifi_network_password = "rjfoewv7nwzg7";
char *esp_thingspeak_api_key_1  = "XRUEOQLI8LL7LDDH"; //JTRON5A_Aus
char *esp_thingspeak_api_key_2  = "N2B2469BMKB14CCS"; //JTRON5B_Aus
https://thingspeak.com/channels/351633
https://freeboard.io/board/SAw7iZ
*/

    /*Australia  JTRON6
     */
char *esp_thingspeak_api_key_1  = "ROSLO0MJM6OTAMFM"; //JTRON6A_Aus
char *esp_thingspeak_api_key_2  = "Z3S5TWQE4RLKIDH5"; //JTRON6B_Aus
//https://thingspeak.com/channels/351672
//https://thingspeak.com/channels/351673
//https://freeboard.io/board/n9paiZ
   







mDot    *dot = NULL;

bool     radio_gateway_rx_ready;
uint8_t *radio_gateway_rx_data;
uint32_t radio_gateway_rx_length;
int16_t  radio_gateway_rx_rssi;


int main() {
    //wait(5);
    uint8_t esp_ip_status;
    int8_t return_status;
    struct sensor_data_raw data_raw_packed;
    struct sensor_data     data_packed;
    status_led_external = 1;
    
    status_led_blink_start(1);
     wait(5);
    // Initialize the ESP.
    esp_reset = 1;
    wait(2);

    esp_serial.printf("AT+RST\r\n");
    debug_serial.printf("AT+RST\r\n");
    esp_wait_for_response(15, "ready");

    while(1) {
        esp_ip_status = 0xFF;
        return_status = esp_get_ip_status(15, &esp_ip_status);
        esp_wait_for_reply(1);
        
        if(return_status != 0) {
            debug_serial.printf("esp_get_ip_status failed:");
            if(return_status == 1) debug_serial.printf("timeout");
            else if(return_status == 2) debug_serial.printf("invalid response");
            debug_serial.printf("\r\n");
        } else {
            if(esp_ip_status == 2) {
                debug_serial.printf("esp is connected to wifi\r\n");
                break;
            } else if(esp_ip_status == 5) {
                debug_serial.printf("esp is not connected to wifi\r\n");
                
                esp_serial.printf("AT+CWMODE=1\r\n");
                debug_serial.printf("AT+CWMODE=1\r\n");
                esp_wait_for_reply(5);
                
                esp_serial.printf("AT+CIPMUX=1\r\n");
                debug_serial.printf("AT+CIPMUX=1\r\n");
                esp_wait_for_reply(5);
                
                esp_serial.printf("AT+CWJAP=\"%s\",\"%s\"\r\n", esp_wifi_network_ssid, esp_wifi_network_password);
                debug_serial.printf("AT+CWJAP=\"%s\",\"%s\"\r\n", esp_wifi_network_ssid, esp_wifi_network_password);
                esp_wait_for_reply(20);
            } else {
                debug_serial.printf("esp returned an unexpected ip status:%i\r\n", esp_ip_status);
            }
        }
    }
    
    // Initialize the LoRa radio.
    uint8_t radio_data_rate, radio_power, radio_frequency_band;
    uint32_t radio_frequency;
    lora::ChannelPlan* plan;
    RadioEvent event;
    
    radio_gateway_rx_ready = false;
    
    // Configure the logging level and instatiate the mDot with the correct channel plan.
    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
    
#if RADIO_CHANNEL_PLAN == CP_US915
    plan = new lora::ChannelPlan_US915();
#elif RADIO_CHANNEL_PLAN == CP_AU915
    plan = new lora::ChannelPlan_AU915();
#elif RADIO_CHANNEL_PLAN == CP_EU868
    plan = new lora::ChannelPlan_EU868();
#elif RADIO_CHANNEL_PLAN == CP_KR920
    plan = new lora::ChannelPlan_KR920();
#elif RADIO_CHANNEL_PLAN == CP_AS923
    plan = new lora::ChannelPlan_AS923();
#elif RADIO_CHANNEL_PLAN == CP_AS923_JAPAN
    plan = new lora::ChannelPlan_AS923_Japan();
#elif RADIO_CHANNEL_PLAN == CP_IN865
    plan = new lora::ChannelPlan_IN865();
#endif
    assert(plan);
    
    dot = mDot::getInstance(plan);
    assert(dot);
    dot->setLogLevel(mts::MTSLog::TRACE_LEVEL);
    
    
    // Return the mdot to a known state.
    dot->resetConfig();
    
    // Attach the custom events handler.
    dot->setEvents(&event);
    
    // Configure MDOT network settings.
    if (dot->getJoinMode() != mDot::PEER_TO_PEER) {
        logInfo("changing network join mode to PEER_TO_PEER");
        if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) {
            logError("failed to set network join mode to PEER_TO_PEER");
        }
    }
    
    radio_frequency_band = dot->getFrequencyBand();
    switch (radio_frequency_band) {
        case lora::ChannelPlan::EU868_OLD:
        case lora::ChannelPlan::EU868:
            // 250kHz channels achieve higher throughput
            // DR_6 : SF7 @ 250kHz
            // DR_0 - DR_5 (125kHz channels) available but much slower
            radio_frequency = 869850000;
            radio_data_rate = lora::DR_6;
            // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
            radio_power = 4;
            break;

        case lora::ChannelPlan::US915_OLD:
        case lora::ChannelPlan::US915:
        case lora::ChannelPlan::AU915_OLD:
        case lora::ChannelPlan::AU915:
            // 500kHz channels achieve highest throughput
            // DR_8 : SF12 @ 500kHz
            // DR_9 : SF11 @ 500kHz
            // DR_10 : SF10 @ 500kHz
            // DR_11 : SF9 @ 500kHz
            // DR_12 : SF8 @ 500kHz
            // DR_13 : SF7 @ 500kHz
            // DR_0 - DR_3 (125kHz channels) available but much slower
            radio_frequency = 915500000;
            radio_data_rate = lora::DR_13;
            // 915 bands have no duty cycle restrictions, set tx power to max
            radio_power = 20;
            break;

        case lora::ChannelPlan::AS923:
        case lora::ChannelPlan::AS923_JAPAN:
            // 250kHz channels achieve higher throughput
            // DR_6 : SF7 @ 250kHz
            // DR_0 - DR_5 (125kHz channels) available but much slower
            radio_frequency = 924800000;
            radio_data_rate = lora::DR_6;
            radio_power = 16;
            break;

        case lora::ChannelPlan::KR920:
            // DR_5 : SF7 @ 125kHz
            radio_frequency = 922700000;
            radio_data_rate = lora::DR_5;
            radio_power = 14;
            break;

        default:
            while (true) {
                logFatal("no known channel plan in use - extra configuration is needed!");
                wait(5);
            }
    }
    
    update_peer_to_peer_config(radio_network_address, radio_network_session_key, radio_data_session_key, radio_frequency, radio_data_rate, radio_power);
    
    // Save changes to configuration.
    logInfo("saving configuration");
    if (!dot->saveConfig()) {
        logError("failed to save configuration");
    }

    // Display configuration.
    display_config();
    
    status_led_blink_stop();
    status_led_set(1, 0);
    
    while(true) {
        // Make sure to stay connected to the network.
        if (!dot->getNetworkJoinStatus()) {
            join_network();
        }
            
        if(button.read() == 1) {
            logDebug("Button press.");
            status_led_blink(STATUS_LED_CHECK);
        }
        
        if(radio_gateway_rx_ready) {
            radio_gateway_rx_ready = false;
        
            if(radio_gateway_rx_length != sizeof(struct sensor_data_raw)) {
                logError("Incorrect packet size (%i should be %i).", radio_gateway_rx_length, sizeof(struct sensor_data_raw));
            } else {
                status_led_blink(STATUS_LED_RADIO_ACTIVITY);
                
                serialize_bytes_to_sensor(radio_gateway_rx_data, &data_raw_packed);
                    
                data_packed.reading_number      = data_raw_packed.reading_number;
                data_packed.voltage_battery     = (float)(data_raw_packed.voltage_battery) / BATTERY_VOLTAGE_SCALE;
                for(int j = 0; j < 9; j++) {
                    data_packed.voltage_wire[j] = data_raw_packed.voltage_wire[j];
                }
                data_packed.temperature         = (float)(data_raw_packed.temperature) / TEMPERATURE_READING_SCALE;
                data_packed.rssi                = (float)(radio_gateway_rx_rssi);
                
                
                char buf1[140], buf2[30];
                
                // Begin HTTP connection through the ESP.
                esp_serial.printf("AT+CIPSTART=4,\"TCP\",\"api.thingspeak.com\",80\r\n");
                debug_serial.printf("AT+CIPSTART=4,\"TCP\",\"api.thingspeak.com\",80\r\n");
                esp_wait_for_reply(2);
                
                // Send data set 1 (battery, signal 1-1, 2-2, 3-3, temperature, rssi) to ThingSpeak.
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("POST /update HTTP/1.1\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("POST /update HTTP/1.1\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("POST /update HTTP/1.1\r\n");
                debug_serial.printf("POST /update HTTP/1.1\r\n");
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Host: api.thingspeak.com\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Host: api.thingspeak.com\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Host: api.thingspeak.com\r\n");
                debug_serial.printf("Host: api.thingspeak.com\r\n");
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Connection: close\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Connection: close\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Connection: close\r\n");
                debug_serial.printf("Connection: close\r\n");
                esp_wait_for_reply(1);
                
                
                memset(buf1, 0, sizeof(buf1));
                sprintf(buf1, "X-THINGSPEAKAPIKEY: %s\r\n", esp_thingspeak_api_key_1);
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf1);
                debug_serial.printf("%s", buf1);
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Content-Type: application/x-www-form-urlencoded\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Content-Type: application/x-www-form-urlencoded\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Content-Type: application/x-www-form-urlencoded\r\n");
                debug_serial.printf("Content-Type: application/x-www-form-urlencoded\r\n");
                esp_wait_for_reply(1);
                
                
                memset(buf1, 0, sizeof(buf1));
                memset(buf2, 0, sizeof(buf2));
                
                sprintf(buf1, "%s&field1=%i&field2=%.2f&field3=%i&field4=%i&field5=%i&field6=%.2f&field7=%.2f\r\n\r\n",
                        esp_thingspeak_api_key_1,
                        data_packed.reading_number,
                        data_packed.voltage_battery,
                        data_packed.voltage_wire[0],
                        data_packed.voltage_wire[4],
                        data_packed.voltage_wire[8],
                        data_packed.temperature,
                        data_packed.rssi);
                sprintf(buf2, "Content-Length: %i\r\n\r\n", strlen(buf1));
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf2));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf2));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf2);
                debug_serial.printf("%s", buf2);
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf1);
                debug_serial.printf("%s", buf1);
                esp_wait_for_reply(2);
                
                wait(15);
                
                // Begin HTTP connection through the ESP.
                esp_serial.printf("AT+CIPSTART=4,\"TCP\",\"api.thingspeak.com\",80\r\n");
                debug_serial.printf("AT+CIPSTART=4,\"TCP\",\"api.thingspeak.com\",80\r\n");
                esp_wait_for_reply(2);
                
                // Send data set 2 (signal 1-2, 1-3, 2-1, 2-3, 3-1, 3-2) to ThingSpeak.
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("POST /update HTTP/1.1\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("POST /update HTTP/1.1\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("POST /update HTTP/1.1\r\n");
                debug_serial.printf("POST /update HTTP/1.1\r\n");
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Host: api.thingspeak.com\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Host: api.thingspeak.com\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Host: api.thingspeak.com\r\n");
                debug_serial.printf("Host: api.thingspeak.com\r\n");
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Connection: close\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Connection: close\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Connection: close\r\n");
                debug_serial.printf("Connection: close\r\n");
                esp_wait_for_reply(1);
                
                
                memset(buf1, 0, sizeof(buf1));
                sprintf(buf1, "X-THINGSPEAKAPIKEY: %s\r\n", esp_thingspeak_api_key_2);
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf1);
                debug_serial.printf("%s", buf1);
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Content-Type: application/x-www-form-urlencoded\r\n"));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen("Content-Type: application/x-www-form-urlencoded\r\n"));
                esp_wait_for_reply(1);
                
                esp_serial.printf("Content-Type: application/x-www-form-urlencoded\r\n");
                debug_serial.printf("Content-Type: application/x-www-form-urlencoded\r\n");
                esp_wait_for_reply(1);
                
                
                memset(buf1, 0, sizeof(buf1));
                memset(buf2, 0, sizeof(buf2));
                
                sprintf(buf1, "%s&field1=%i&field2=%i&field3=%i&field4=%i&field5=%i&field6=%i&field7=%i\r\n\r\n",
                        esp_thingspeak_api_key_2,
                        data_packed.reading_number,
                        data_packed.voltage_wire[1],
                        data_packed.voltage_wire[2],
                        data_packed.voltage_wire[3],
                        data_packed.voltage_wire[5],
                        data_packed.voltage_wire[6],
                        data_packed.voltage_wire[7]);
                sprintf(buf2, "Content-Length: %i\r\n\r\n", strlen(buf1));
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf2));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf2));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf2);
                debug_serial.printf("%s", buf2);
                esp_wait_for_reply(1);
                
                
                esp_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                debug_serial.printf("AT+CIPSEND=4,%i\r\n", strlen(buf1));
                esp_wait_for_reply(1);
                
                esp_serial.printf("%s", buf1);
                debug_serial.printf("%s", buf1);
                esp_wait_for_reply(2);
            }
        }
    }
}

void esp_wait_for_reply(float timeout) {
    timer.reset();
    timer.start();
    
    while(timer.read() < timeout) {
        if(esp_serial.readable()) {
            debug_serial.putc(esp_serial.getc());
        }
    }
    
    timer.stop();
}

int8_t esp_wait_for_response(float timeout, char *response) {
    int8_t return_value;
    char c;
    uint32_t response_index, response_length;
    
    return_value = 0;
    
    response_length = strlen(response);
    
    timer.reset();
    timer.start();
    
    while(1) {
        if(esp_serial.readable()) {
            c = esp_serial.getc();
            debug_serial.putc(c);
            
            if(response[response_index] == c) {
                response_index++;
            } else {
                response_index = 0;
            }
            
            if(response_index == response_length) break;
        }
        
        if(timer.read() > timeout) {
            return_value = 1;
            break;
        }
    }
    
    timer.stop();
    return return_value;
}

int8_t esp_get_ip_status(float timeout, uint8_t *ip_status) {
    uint8_t ip_status_index, ip_status_string_length;
    char c;
    char *ip_status_string = "STATUS:";
    
    esp_serial.printf("AT+CIPSTATUS\r\n");
    debug_serial.printf("AT+CIPSTATUS\r\n");
    
    ip_status_string_length = 7;
    
    timer.reset();
    timer.start();
    
    ip_status_index = 0;
    
    while(1) {
        if(esp_serial.readable()) {
            c = esp_serial.getc();
            debug_serial.putc(c);
            
            if(ip_status_index == ip_status_string_length) {
                timer.stop();
                
                if(c < '0' || c > '9') return 2;
                (*ip_status) = c - '0';
                return 0;
            }
            
            if(ip_status_string[ip_status_index] == c) {
                ip_status_index++;
            } else {
                ip_status_index = 0;
            }
        }
        
        if(timer.read() > timeout) {
            timer.stop();
            return 1;
        }
    }
}