this is using the mbed os version 5-13-1

Dependencies:   mbed-http

source/main-https.cpp

Committer:
ocomeni
Date:
2019-02-28
Revision:
73:6f5021cbe752
Child:
74:f26e846adfe9

File content as of revision 73:6f5021cbe752:

#define MBED_CONF_MBED_TRACE_ENABLE 1

#include "select-demo.h"

#if DEMO == DEMO_HTTPS

//#include "mbed.h"
#include <events/mbed_events.h>
#include <mbed.h>
#include "ble/BLE.h"
//#include "BLE.h"
#include "mbed_trace.h"
#include "https_request.h"
#include "http_request.h"
#include "network-helper.h"
#include "ATCmdParser.h"
//#include "BLEDevice.h"

#include "LEDService.h"
#include "ble/services/UARTService.h"

UARTService *uart;

DigitalOut alivenessLED(LED1, 0);
DigitalOut actuatedLED(LED2, 0);

#define   DEFAULT_BAUD_RATE   115200

RawSerial *device; // tx, rx
UARTSerial *_serial; // tx, rx
ATCmdParser *_parser;
const static char     DEVICE_NAME[] = "BLE-UART";
static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
#define BUFFER_LEN 256
#define TX_BUFFER_LEN 4*256
#define RX_BUFFER_LEN 4*256
char buffer[BUFFER_LEN];
uint8_t TxBuffer[TX_BUFFER_LEN];
uint8_t RxBuffer[RX_BUFFER_LEN];
static EventQueue eventQueue(/* event count */ 20 * EVENTS_EVENT_SIZE);
//static EventQueue eventQueue2(/* event count */ 10 * EVENTS_EVENT_SIZE);

LEDService *ledServicePtr;

Thread t;

/* List of trusted root CA certificates
 * currently two: GlobalSign, the CA for os.mbed.com and Let's Encrypt, the CA for httpbin.org
 *
 * To add more root certificates, just concatenate them.
 */
#include "https_certificates.h"



void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void) params;
    BLE::Instance().gap().startAdvertising();
}

void blinkCallback(void)
{
    alivenessLED = !alivenessLED; /* Do blinky on LED1 to indicate system aliveness. */
}

void EchoBleUartReceived()
{
    uart->writeString(buffer);
    uart->writeString("\n");    //flushes uart output buffer and sends data
}

/**
 * This callback allows the LEDService to receive updates to the ledState Characteristic.
 *
 * @param[in] params
 *     Information about the characterisitc being updated.
 */
void onDataWrittenCallback(const GattWriteCallbackParams *params) {
    if ((params->handle == ledServicePtr->getValueHandle()) && (params->len == 1)) {
        actuatedLED = *(params->data);
    }
    else if ((uart != NULL) && (params->handle == uart->getTXCharacteristicHandle())) {
        uint16_t bytesRead = params->len;

        printf("received %u bytes\n\r ", bytesRead);

        if(bytesRead >= 255){
            printf("Overflow command %u n\r ", bytesRead);
            bytesRead = 255;
        }

        unsigned index = 0;
        for (; index < bytesRead; index++) {
            buffer[index] = params->data[index];
        }

        buffer[index++] = 0;

        printf("Data : %s ",buffer);
        printf("\r\n");
        eventQueue.call(EchoBleUartReceived);

    }
}


/**
 * This function is called when the ble initialization process has failled
 */
void onBleInitError(BLE &ble, ble_error_t error)
{
    printf("\n BLE Initialization failed!! \n");
    
    /* Initialization error handling should go here */
}

void printMacAddress()
{
    /* Print out device MAC address to the console*/
    Gap::AddressType_t addr_type;
    Gap::Address_t address;
    BLE::Instance().gap().getAddress(&addr_type, address);
    printf("DEVICE MAC ADDRESS: ");
    for (int i = 5; i >= 1; i--){
        printf("%02x:", address[i]);
    }
    printf("%02x\r\n", address[0]);
}

/**
 * Callback triggered when the ble initialization process has finished
 */
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        /* In case of error, forward the error handling to onBleInitError */
        onBleInitError(ble, error);
        return;
    }

    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);
    ble.gattServer().onDataWritten(onDataWrittenCallback);

    bool initialValueForLEDCharacteristic = false;
    ledServicePtr = new LEDService(ble, initialValueForLEDCharacteristic);
    /* Setup primary service */
    uart = new UARTService(ble);

    /* setup advertising */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    /* set up the services that can be discovered */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
    ble.gap().startAdvertising();

    printMacAddress();
}

void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
    BLE &ble = BLE::Instance();
    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
}


void bleInitialization()
{
    BLE &ble = BLE::Instance();
    device->printf("\n --- BLE Instance Instantiated --- \n");
    ble.onEventsToProcess(scheduleBleEventsProcessing);
    device->printf("\n --- BLE scheduleBleEventsProcessing setup --- \n");
    ble.init(bleInitComplete);
}


static int uartExpectedRcvCount = 0;
static int uartCharRcvCount = 0;
static bool UartBusy = false;
int WriteUartBytes(const uint8_t * txBuffer, size_t bufSize, int txLen)
{
    if(txLen > bufSize)
    {
        txLen = bufSize;
    }
    //int goodTxLen;
    //goodTxLen = _parser.write((const char *) txBuffer, txLen);
    for(int i=0;i<txLen;i++)
    {
        device->putc(txBuffer[i]);
    }
    // return number of bytes written to UART
    return (int) txLen;
}

void UartRxcallback_ex() {
    if(uartCharRcvCount >= uartExpectedRcvCount)
    {
        int x = device->getc();
        return;
    }
    if(uartCharRcvCount == 0)
    {
        device->printf("\nFirst Call to UART attach callback!!\n");
    }
    // Note: you need to actually read from the serial to clear the RX interrupt
    RxBuffer[uartCharRcvCount] = (uint8_t) device->getc();
    uartCharRcvCount++;
    if(uartCharRcvCount >= uartExpectedRcvCount)
    {
        alivenessLED = !alivenessLED; /* Do blinky on LED1 to indicate system aliveness. */
        device->printf("\nNumber of Received Bytes = %d\n\n", uartCharRcvCount);
        device->printf("--- Writing back received bytes --- \n");
        int n;
        n = WriteUartBytes(RxBuffer, TX_BUFFER_LEN, uartCharRcvCount);
        UartBusy = false;
    }
}

void BackGndUartRead(uint8_t * rxBuffer, size_t bufSize, int rxLen)
{
    UartBusy = true;
    device->printf("Setting up background UART read -  rxLen = %d\n", rxLen);
    uartCharRcvCount = 0;
    if(rxLen > bufSize)
    {
        rxLen = bufSize;
    }
    uartExpectedRcvCount = rxLen;
    device->attach(&UartRxcallback_ex);
    device->printf("\nBackground UART read setup completed\n\n");
    //for(int i=0;i<rxLen;i++)
    //{
    //    rxBuffer[i] = (uint8_t) getc();
    //}
    // return number of bytes written to UART
    //return rxLen;
}

int ReadUartBytes(uint8_t * rxBuffer, size_t bufSize, int rxLen, bool echo)
{
    UartBusy = true;
    if(rxLen > bufSize)
    {
        rxLen = bufSize;
    }
    for(int i=0;i<rxLen;i++)
    {
        rxBuffer[i] = (uint8_t) device->getc();
        if(echo)device->putc(rxBuffer[i]);
    }
    UartBusy = false;
    //return number of bytes written to UART
    return rxLen;
}


void checkUartReceive()
{
    //device->printf("Hello World!\n\r");
    char cbuf[100];
    int rxCnt=0;
    while(device->readable()) {
        //device->printf("uartCharRcvCount = %d\n\r", uartCharRcvCount++);
        cbuf[rxCnt++] = device->getc();
        //putc(getc() + 1); // echo input back to terminal
    }
    cbuf[rxCnt] = NULL;
    if(rxCnt > 0)
    {
        device->printf("received %d chars\n", rxCnt);
        device->printf("%s\n", cbuf);
    }

}
uint64_t lastTime = 0;
uint64_t now = 0;
uint32_t callCount = 0;
void HelloUart()
{
    //if(UartBusy)return;
    // 64-bit time doesn't wrap for half a billion years, at least
    lastTime = now;
    now = Kernel::get_ms_count();
    callCount++;
    device->printf("\nHello : %d secs elapsed : CallCount = %d \n", uint32_t(now - lastTime), callCount);
}




//Serial device(USBTX, USBRX); // tx, rx
//RawSerial device(MBED_CONF_APP_UART1_TX, MBED_CONF_APP_UART1_RX); // tx, rx


int chunkNum;
void dump_response(HttpResponse* res) {
    device->printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str());

    device->printf("Headers:\n");
    for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
        device->printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str());
    }
    device->printf("\nBody (%lu bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str());
}

void completed(){
    }
void dump_chunked_response(const char *at, uint32_t length) {
    device->printf("\n Chunked response: Chunk %d : Total Bytes = %d\n", chunkNum , length);
    //device->printf("\n Try Print Header as string:\n\n ");
    //device->printf("recv %d [%.*s]\n", length, strstr((char *)at, "\r\n")-(char *)at, (char *)at);
    //if(false)
    if(chunkNum < 2)
    for(int i=0; i < length; i++){
        
        while(device->writeable())
        {
            device->putc((uint8_t)at[i]);
        }
        //int resp = write( (const uint8_t *)at, (int) length, &completed, SERIAL_EVENT_TX_COMPLETE);
    }
    if(false)
    for (size_t ix = 0; ix < length; ix++) {
        device->printf("%02X: ", at[ix]);
        if((ix % 32) == 0 and ix)
        device->printf("\n");
    }
    device->printf("\n\n");
    chunkNum++;
    //device->printf("\nBody (%lu bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str());
}


// Wifi-demo
void wifi_demo(NetworkInterface* network){
    if (!network) {
        device->printf("Cannot connect to the network, see serial output\n");
        return 1;
    }

    mbed_trace_init();

    // GET request to os.mbed.com
    {
        chunkNum = 0;
        device->printf("\n----- HTTPS GET request -----\n");

        HttpsRequest* get_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_GET, "https://os.mbed.com/media/uploads/mbed_official/hello.txt", &dump_chunked_response);

        HttpResponse* get_res = get_req->send();
        if (!get_res) {
            device->printf("HttpRequest failed (error code %d)\n", get_req->get_error());
            return 1;
        }
        device->printf("\n----- HTTPS GET response -----\n");
        dump_response(get_res);
        delete get_req;
    }
    
    
    
     // Do a GET request to httpbin.org
    {
        chunkNum = 0;
        device->printf("\n----- HTTP GET request to httpbin.org  -----\n");

        // By default the body is automatically parsed and stored in a buffer, this is memory heavy.
        // To receive chunked response, pass in a callback as last parameter to the constructor.
        HttpRequest* get_req = new HttpRequest(network, HTTP_GET, "http://httpbin.org/status/418");

        HttpResponse* get_res = get_req->send();
        if (!get_res) {
            device->printf("HttpRequest failed (error code %d)\n", get_req->get_error());
            return 1;
        }

        device->printf("\n----- HTTP GET response from httpbin.org -----\n");
        dump_response(get_res);

        delete get_req;
    }
    
    
    // Do a GET request to ovh.net
    if(false)
    {
       chunkNum = 0;
       device->printf("\n----- HTTP GET request to ovh.net  -----\n");
        Timer t;
        // By default the body is automatically parsed and stored in a buffer, this is memory heavy.
        // To receive chunked response, pass in a callback as last parameter to the constructor.
        t.start();
        HttpRequest* get_req = new HttpRequest(network, HTTP_GET, "http://www.ovh.net/files/1Mio.dat", &dump_chunked_response);

        HttpResponse* get_res = get_req->send();
        if (!get_res) {
            device->printf("HttpRequest failed (error code %d)\n", get_req->get_error());
            return 1;
        }

        device->printf("\n----- HTTP GET response from ovh.net -----\n");
        dump_response(get_res);
        t.stop();
        device->printf("The time taken was %f seconds\n", t.read());


        delete get_req;
    }
    
    {
        device->printf("\n----- HTTPS GET request (large file!) -----\n");

        HttpsRequest* get_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_GET, "https://os.mbed.com/media/uploads/mbed_official/hello.txt");

        HttpResponse* get_res = get_req->send();
        if (!get_res) {
            device->printf("HttpRequest failed (error code %d)\n", get_req->get_error());
            return 1;
        }
        /*
        while (0 < (response = socket.recv(p, remaining))) {
            p += response;
            rcount += response;
            remaining -= response;
        }
        */
        device->printf("\n----- HTTPS GET response -----\n");
        dump_response(get_res);



        delete get_req;
    }

    // POST request to httpbin.org
    {
        device->printf("\n----- HTTPS POST request -----\n");

        HttpsRequest* post_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_POST, "https://httpbin.org/post");
        post_req->set_header("Content-Type", "application/json");

        const char body[] = "{\"hello\":\"world\"}";

        HttpResponse* post_res = post_req->send(body, strlen(body));
        if (!post_res) {
            device->printf("HttpRequest failed (error code %d)\n", post_req->get_error());
            return 1;
        }

        device->printf("\n----- HTTPS POST response -----\n");
        dump_response(post_res);

        delete post_req;
    }


    // POST request to ws.dnanudge.io:80
    {
        device->printf("\n----- HTTP POST request (http://ws.dnanudge.io/nudgebox/v1) -----\n");

        HttpRequest* post_req = new HttpRequest(network, HTTP_POST, "http://ws.dnanudge.io/nudgebox/v1");
        post_req->set_header("Host", "ws.dnanudge.io");
        post_req->set_header("Accept", "*/*");
        post_req->set_header("Content-Type", "application/octet-stream");
        post_req->set_header("Content-Length", "20");
                               // 00    08    6a    48    f8    2d    8e    82    01    68
        const uint8_t body[] = {0x00, 0x08, 0x6a, 0x48, 0xf8, 0x2d, 0x8e, 0x82, 0x01, 0x68, 
                               // 65    6c    6c    6f    00    00    67    c3    19    f8
                                0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x67, 0xc3, 0x19, 0xf8};

        HttpResponse* post_res = post_req->send(body, 20);
        if (!post_res) {
            device->printf("HttpRequest failed (error code %d)\n", post_req->get_error());
            return 1;
        }

        device->printf("\n----- HTTPS POST response -----\n");
        dump_response(post_res);

        delete post_req;
    }


    // POST request to httpbin.org
    if(false)
    {
        device->printf("\n----- HTTPS POST request to AWS -----\n");

        HttpsRequest* post_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_POST, "https://q6bc0dxw7f.execute-api.eu-west-2.amazonaws.com/test/samples/v1");
        post_req->set_header("Content-Type", "application/json");

        const char body[] = 
                            "{"
                            "\"firstName\": \"Maria\", "
                            "\"lastName\": \"Huntera\", "
                            "\"dob\": \"1970-12-03\", "
                            "\"mobile\": \"07841887580\", "
                            "\"cartridgeId\": \"DN00000000RMPOE\", "
                            "\"labSampleId\": \"DYYAK\""
                            "}";
        HttpResponse* post_res = post_req->send(body, strlen(body));
        if (!post_res) {
            device->printf("HttpRequest failed (error code %d)\n", post_req->get_error());
            return 1;
        }

        device->printf("\n----- HTTPS POST response from AWS -----\n");
        dump_response(post_res);

        delete post_req;
    }
 }

int main() {
    //RawSerial *device(USBTX, USBRX); // tx, rx
    device = new RawSerial(USBTX, USBRX, DEFAULT_BAUD_RATE);
    
    device->printf("\n --- Running UART-BLE-UartService --- \n");
    // Start the event queue
    //t.start(callback(&eventQueue, &EventQueue::dispatch_forever));

    eventQueue.call_every(500, blinkCallback);
    eventQueue.call_every(60000, HelloUart);
    //eventQueue.call_every(1000, checkUartReceive);
    device->printf("\n --- EventQueues setup --- \n");
    ////////////////////////////////////////////////////////////////////////////////
    // BLE Initialization /////////////////////////////////////////////////////////
    device->printf("\n --- about to instantiate BLE instance --- \n");
    device->getc();
    //cbMAIN_driverLock();
    BLE &ble = BLE::Instance();
    device->printf("\n --- BLE Instance Instantiated --- \n");
    //ble.onEventsToProcess(scheduleBleEventsProcessing);
    //device->printf("\n --- BLE scheduleBleEventsProcessing setup --- \n");
    //ble.init(bleInitComplete);
    bleInitialization();
    //cbMAIN_driverUnlock();
    device->printf("\n --- BLE Initialization completed --- \n");
    device->printf("\n Press any key to start Wifi demo: ");
    device->getc();
    ////////////////////////////////////////////////////////////////////////////////////

    //device->baud(115200);
     NetworkInterface* network = connect_to_default_network_interface();
     // run on separate thread;
     t.start(wifi_demo(network));
     network->disconnect();   
     t.join(); 
    
    for(int i=0;i<255;i++)
    {
        device->putc(i);
    }
    int n;
    //ReadUartBytes(RxBuffer, RX_BUFFER_LEN, 4);
    device->printf("\n\n\nEnter # of expected bytes: ");
    n = ReadUartBytes(RxBuffer, RX_BUFFER_LEN, 4, true);
    int rxLen = (int) 100*(RxBuffer[0]-'0') + 10*(RxBuffer[1]-'0') + (RxBuffer[2]-'0');
    device->printf("\n\nExpected # of Received Bytes = %d\n", rxLen);
    BackGndUartRead(RxBuffer, RX_BUFFER_LEN, rxLen);
    //device->printf("--- Writing back received data --- \n\n");
    //n = WriteUartBytes(RxBuffer, TX_BUFFER_LEN, rxLen);
    //write("\n\ntesting Serial Write\n", 40); //, checkUartReceive, SERIAL_EVENT_TX_COMPLETE);
 

    device->printf("\nATCmdParser with ESP8266 example");
    device->printf("\n Waiting for 2 minutes ");
    wait(120);
    eventQueue.dispatch_forever();
    return 0;
    device->printf("\n About to delete RawSerial device instance ");
    delete device;
    _serial = new UARTSerial(USBTX, USBRX, DEFAULT_BAUD_RATE);
    printf("\n ATCmdParser printf being used now \n\n");
    _parser = new ATCmdParser(_serial);
    _parser->debug_on( 1 );
    _parser->set_delimiter( "\r\n" );

    //Now get the FW version number of ESP8266 by sending an AT command
    printf("\nATCmdParser: Retrieving FW version");
    _parser->send("AT+GMR");
    int version;
    if(_parser->recv("SDK version:%d", &version) && _parser->recv("OK")) {
        printf("\nATCmdParser: FW version: %d", version);
        printf("\nATCmdParser: Retrieving FW version success");
    } else {
        printf("\nATCmdParser: Retrieving FW version failed");
        return -1;
    }

    printf("\nDone\n");


    //eventQueue.dispatch_forever();
    //t.start(callback(&eventQueue, &EventQueue::dispatch_forever));
    //eventQueue2.dispatch_forever();

    return 0;




    //wait(osWaitForever);
}

#endif