
this is using the mbed os version 5-13-1
Diff: source/main-https.cpp
- Revision:
- 73:6f5021cbe752
- Child:
- 74:f26e846adfe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-https.cpp Thu Feb 28 18:13:48 2019 +0000 @@ -0,0 +1,617 @@ +#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