Doug Anson / mbedEndpointNetwork_BLE

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Files at this revision

API Documentation at this revision

Comitter:
ansond
Date:
Sat Feb 14 07:36:17 2015 +0000
Parent:
1:faa02c5fd781
Child:
3:0f1bb62ac043
Commit message:
updates

Changed in this revision

NSDL/libnsdl.lib Show diff for this revision Revisions of this file
NSDL/libnsdl_src.lib Show annotated file Show diff for this revision Revisions of this file
NSDL/nsdl_support.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
bt_network/Base64.lib Show annotated file Show diff for this revision Revisions of this file
bt_network/Socket/Endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/Socket/Endpoint.h Show annotated file Show diff for this revision Revisions of this file
bt_network/Socket/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/Socket/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/SplitterAssembler.lib Show annotated file Show diff for this revision Revisions of this file
bt_network/mbed-rtos.lib Show diff for this revision Revisions of this file
network_stubs/network_stubs.cpp Show annotated file Show diff for this revision Revisions of this file
network_stubs/network_stubs.h Show annotated file Show diff for this revision Revisions of this file
--- a/NSDL/libnsdl.lib	Wed Feb 11 23:01:05 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://developer.mbed.org/users/ansond/code/libnsdl/#9cb268b96ffb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NSDL/libnsdl_src.lib	Sat Feb 14 07:36:17 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/ansond/code/libnsdl_src/#9ea5eb5c2173
--- a/NSDL/nsdl_support.cpp	Wed Feb 11 23:01:05 2015 +0000
+++ b/NSDL/nsdl_support.cpp	Sat Feb 14 07:36:17 2015 +0000
@@ -11,11 +11,13 @@
 #endif
 #define DBG  std::printf
 
-#include "rtos.h"
-
 #include "UDPSocket.h"
 #include "Endpoint.h"
 
+#include "BLEDevice.h"
+
+extern BLEDevice ble;
+
 Endpoint nsp;
 UDPSocket server;
 
@@ -127,24 +129,16 @@
     nsdl_clean_register_endpoint(&endpoint_ptr);
 }
 
-void registration_update_thread(void const *args) {
-    int count = -1;
-    int registration_time = 15;      // about 30 seconds if iteration every 2 seconds
-    
-    // first we want to wait a bit... let the endpoint crank up...
-    Thread::wait(NSP_RD_UPDATE_PERIOD);   // wait about 30 seconds, then go ahead and start the re-registration interval...  
-                
-    // now loop this thread forever sleeping and re-registering at the right iteration.
-    while(true) {
-        Thread::wait(MAIN_LOOP_SLEEP);
-        ++count;
-        if (count%registration_time == 0) {
-            // re-registration time!
-            count = 0;
-            DBG("NSP: (re)registering...\r\n");
-            register_endpoint(false);
-            DBG("NSP: (re)registering complete.\r\n");
-        }
+// Simple Ticker-based re-registration updating... 
+void registration_update_tick(void) {
+    extern bool __registered;
+    if (__registered) { 
+        DBG("NSP: (re)registering...\r\n");
+        register_endpoint(false);
+        DBG("NSP: (re)registering complete.\r\n");
+    }
+    else {
+        DBG("NSP: BLE not connected. Skipping re-registration...\r\n");
     }
 }
 
@@ -177,26 +171,35 @@
     nsp.set_address(NSP_address_str,nsp_port);
 }
 
+extern "C" volatile bool __registered;
+
 // NSP event loop - spawn a re-registration thread AFTER we have initially registered and begun event processing...     
 void nsdl_event_loop() {    
     sn_nsdl_addr_s received_packet_address; 
     Endpoint from;
     uint8_t nsp_received_address[4];
     char nsp_buffer[1024];
-
+   
     memset(&received_packet_address, 0, sizeof(sn_nsdl_addr_s));
     memset(nsp_received_address, 0, sizeof(nsp_received_address));
     received_packet_address.addr_ptr = nsp_received_address;    
             
-    // start the registration update thread.. it will wait a bit while the endpoint gins up...
-    Thread registration_thread(registration_update_thread);
+    // re-registration update ticker...
+    Ticker ticker;
+    ticker.attach(registration_update_tick,30); // every 30 seconds...
     
     // FOREVER: main loop for event processing  
-    while(true) {     
-        //DBG("NSP: waiting for data...\r\n");
-        int n = server.receiveFrom(from,nsp_buffer,sizeof(nsp_buffer));
-
-        //DBG("NSP: received %d bytes... processing..\r\n.",n);
-        if (n >= 0) sn_nsdl_process_coap((uint8_t*)nsp_buffer,n,&received_packet_address);        
+    while(true) {   
+        // wait for BLE events...  
+        ble.waitForEvent();
+        
+        // only process if we are registered and thus connected... otherwise ignore
+        if (__registered) {
+            //DBG("NSP: waiting for data...\r\n");
+            int n = server.receiveFrom(from,nsp_buffer,sizeof(nsp_buffer));
+    
+            //DBG("NSP: received %d bytes... processing..\r\n.",n);
+            if (n >= 0) sn_nsdl_process_coap((uint8_t*)nsp_buffer,n,&received_packet_address);  
+        }      
      }
 }
\ No newline at end of file
--- a/bt_network/BLE_API.lib	Wed Feb 11 23:01:05 2015 +0000
+++ b/bt_network/BLE_API.lib	Sat Feb 14 07:36:17 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#1407d2f1ce3c
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#c605f4abee83
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bt_network/Base64.lib	Sat Feb 14 07:36:17 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/ansond/code/Base64/#4920bc5699f3
--- a/bt_network/Socket/Endpoint.cpp	Wed Feb 11 23:01:05 2015 +0000
+++ b/bt_network/Socket/Endpoint.cpp	Sat Feb 14 07:36:17 2015 +0000
@@ -20,29 +20,43 @@
 #include <cstring>
 #include <cstdio>
 
+// BLE network_stubs.cpp linkage
+extern "C" void ble_set_remote_ip_address(const char *ipAddress,const int ipAddressLength);
+extern "C" void ble_set_remote_ip_port(const int ipPort); 
+
 Endpoint::Endpoint()  {
     reset_address();
 }
 Endpoint::~Endpoint() {}
 
 void Endpoint::reset_address(void) {
-    // XXX
-    _ipAddress[0] = '\0';
+    memset(_ipAddress,0,sizeof(_ipAddress));
+    _ipPort = 0;
 }
 
 #include "stdio.h"
 
 int Endpoint::set_address(const char* host, const int port) {
-    // XXX
-    return 0;
+    reset_address();
+    
+    // XXX do we need to worry about hostname->ipaddress mapping for BLE?
+    memcpy(_ipAddress,host,strlen(host));
+    ble_set_remote_ip_address(host,strlen(host));
+    
+    // copy port number
+    _ipPort = port;
+    
+    // BLE also needs it for the connection record
+    ble_set_remote_ip_port(port);
+    
+    // return the port number...
+    return port;
 }
 
 char* Endpoint::get_address() {
-    // XXX
-    return NULL;
+    return _ipAddress;
 }
 
 int   Endpoint::get_port() {
-   // XXX
-   return 0;
+   return _ipPort;
 }
--- a/bt_network/Socket/Endpoint.h	Wed Feb 11 23:01:05 2015 +0000
+++ b/bt_network/Socket/Endpoint.h	Sat Feb 14 07:36:17 2015 +0000
@@ -56,6 +56,7 @@
 
 protected:
     char _ipAddress[17];
+    int _ipPort;
 };
 
 #endif
--- a/bt_network/Socket/Socket.cpp	Wed Feb 11 23:01:05 2015 +0000
+++ b/bt_network/Socket/Socket.cpp	Sat Feb 14 07:36:17 2015 +0000
@@ -20,6 +20,9 @@
 
 using std::memset;
 
+extern "C" void ble_build_disconnection_record();
+extern "C" void ble_send_disconnection_record(); 
+
 Socket::Socket() : _sock_fd(-1), _blocking(true), _timeout(1500) {
     
 }
@@ -30,12 +33,12 @@
 }
 
 int Socket::init_socket(int type) {
-    // XXX
+    // Not used for BLE shim
     return 0;
 }
 
 int Socket::select(struct timeval *timeout, bool read, bool write) {
-    // XXX
+    // Not used for BLE shim...
     return 0;
 }
 
@@ -48,7 +51,8 @@
 }
 
 int Socket::close(bool shutdown) {
-   // XXX
+   ble_build_disconnection_record();
+   ble_send_disconnection_record();
    return 0;
 }
 
--- a/bt_network/Socket/UDPSocket.cpp	Wed Feb 11 23:01:05 2015 +0000
+++ b/bt_network/Socket/UDPSocket.cpp	Sat Feb 14 07:36:17 2015 +0000
@@ -20,70 +20,33 @@
 
 #include <cstring>
 
+// BLE network_stubs.cpp linkage
+extern "C" int ble_recv_data(uint8_t *buffer,int buffer_len);
+extern "C" int ble_send_data(uint8_t *data,int data_len,bool sendHeader);
+extern "C" void ble_set_remote_ip_address(const char *ipAddress,const int ipAddressLength);
+extern "C" void ble_set_remote_ip_port(const int ipPort); 
+
 using std::memset;
 
 UDPSocket::UDPSocket() {
 }
 
 int UDPSocket::init(void) {
-    // XXX
-    //return init_socket(SOCK_DGRAM);
-    
     return 0;
 }
 
 // Server initialization
 int UDPSocket::bind(int port) {
-    /* XXX
-    if (init_socket(SOCK_DGRAM) < 0)
-        return -1;
-    
-    struct sockaddr_in localHost;
-    std::memset(&localHost, 0, sizeof(localHost));
-    
-    localHost.sin_family = AF_INET;
-    localHost.sin_port = htons(port);
-    localHost.sin_addr.s_addr = INADDR_ANY;
-    
-    if (lwip_bind(_sock_fd, (const struct sockaddr *) &localHost, sizeof(localHost)) < 0) {
-        close();
-        return -1;
-    }
-    */
-    
+    ble_set_remote_ip_port(port);
     return 0;
 }
 
 // -1 if unsuccessful, else number of bytes written
 int UDPSocket::sendTo(Endpoint &remote, char *packet, int length) {
-    if (_sock_fd < 0)
-        return -1;
-    
-    if (!_blocking) {
-        TimeInterval timeout(_timeout);
-        if (wait_writable(timeout) != 0)
-            return 0;
-    }
-    
-    // XXX return lwip_sendto(_sock_fd, packet, length, 0, (const struct sockaddr *) &remote._remoteHost, sizeof(remote._remoteHost));
-    return 0;
+    return ble_send_data((uint8_t *)packet,length,true);
 }
 
 // -1 if unsuccessful, else number of bytes received
 int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length) {
-    /* XXX
-    if (_sock_fd < 0)
-        return -1;
-    
-    if (!_blocking) {
-        TimeInterval timeout(_timeout);
-        if (wait_readable(timeout) != 0)
-            return 0;
-    }
-    remote.reset_address();
-    socklen_t remoteHostLen = sizeof(remote._remoteHost);
-    return lwip_recvfrom(_sock_fd, buffer, length, 0, (struct sockaddr*) &remote._remoteHost, &remoteHostLen);
-    */
-    
-    return 0;
+    return ble_recv_data((uint8_t *)buffer,length);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bt_network/SplitterAssembler.lib	Sat Feb 14 07:36:17 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/ansond/code/SplitterAssembler/#5614523d641b
--- a/bt_network/mbed-rtos.lib	Wed Feb 11 23:01:05 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#ab4200083b07
--- a/network_stubs/network_stubs.cpp	Wed Feb 11 23:01:05 2015 +0000
+++ b/network_stubs/network_stubs.cpp	Sat Feb 14 07:36:17 2015 +0000
@@ -1,6 +1,6 @@
 /**
  * @file    network_stubs.cpp
- * @brief   mbed Endpoint network stubs implementation (Ethernet)
+ * @brief   mbed Endpoint network stubs implementation (BLE)
  * @author  Doug Anson
  * @version 1.0
  * @see     
@@ -22,40 +22,227 @@
  
 #include "network_stubs.h"
 
+#include "BLEDevice.h"
+#include "UARTService.h"
+#include "Base64.h"
+#include "SplitterAssembler.h"
+
+// forward declarations
+extern "C" int ble_recv_data(uint8_t *buffer,int buffer_len);
+extern "C" int ble_send_data(uint8_t *data,int data_len,bool sendHeader);
+
 extern "C" {
     
+// Globals
+BLEDevice    ble;
+UARTService *uart = NULL;
+volatile bool __registered = false;
+
+static const uint16_t uuid16_list[] = {GattService::UUID_DEVICE_INFORMATION_SERVICE};
+
+char _ipAddress[IP_ADDRESS_LENGTH];
+int  _ipPort;
+char _connectionRecord[MAX_CONNECTION_RECORD_LENGTH+1];
+
+// record the remote UDPSocket endpoint IP address
+void ble_set_remote_ip_address(const char *ipAddress,const int ipAddressLength)
+{
+    memset(_ipAddress,0,IP_ADDRESS_LENGTH);
+    int length = ipAddressLength;
+    if (length > IP_ADDRESS_LENGTH) length = IP_ADDRESS_LENGTH;
+    if (ipAddress != NULL) memcpy(_ipAddress,ipAddress,length);
+}
+
+// record the remote UDPSocket endpoint port
+void ble_set_remote_ip_port(const int ipPort)
+{
+    _ipPort = ipPort;
+}
+
+// build connection record 
+void ble_build_connection_record() 
+{
+    memset(_connectionRecord,0,MAX_CONNECTION_RECORD_LENGTH+1);
+    sprintf(_connectionRecord,"1|%s|%d\n",_ipAddress,_ipPort);
+    DBG("ble_build_connection_record: Connection Record: %s",_connectionRecord);
+}
+
+// build disconnection record
+void ble_build_disconnection_record() 
+{
+    memset(_connectionRecord,0,MAX_CONNECTION_RECORD_LENGTH+1);
+    printf(_connectionRecord,"0|%s|%d\n",_ipAddress,_ipPort);
+    DBG("ble_build_disconnection_record: Connection Record: %s",_connectionRecord);
+}
+
+// BLE Disconnection callback
+void ble_disconnect_callback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) 
+{
+    DBG("Disconnected handle %u!\r\n", handle);
+    __registered = false;
+    DBG("Restarting the advertising process\r\n");
+    ble.startAdvertising();
+}
+
+// BLE Connection callback
+void ble_connect_callback(Gap::Handle_t handle, Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *params) 
+{
+    if (__registered == false) {
+        DBG("ble_connect_callback: BLE connected! Creating connection record...\r\n");
+        ble_build_connection_record();
+        DBG("ble_connect_callback: Sending connection record...\r\n");
+        ble_send_data((uint8_t *)_connectionRecord,strlen(_connectionRecord),false);
+        
+        // wait a bit... let the gateway connect...
+        wait_ms(2000);
+        
+        // NSP registration
+        DBG("ble_connect_callback: calling NSP registration...\r\n");
+        register_endpoint(true);
+        DBG("ble_connect_callback: NSP registration completed\r\n");
+        
+        // registration completed
+        __registered = true;
+    }
+}
+
+// send the disconnection record
+void ble_send_disconnection_record()
+{
+    DBG("Sending disconnection record...\r\n");
+    ble_send_data((uint8_t *)_connectionRecord,strlen(_connectionRecord),false);
+}
+
+// BLE Init
+void ble_init(void) 
+{
+    // BLE initialization and callback setup
+    ble.init();
+    ble.onDisconnection(ble_disconnect_callback);
+    ble.onConnection(ble_connect_callback);
+}
+
+// BLE Begin Advertising
+void ble_begin_advertising(void) 
+{
+    extern uint8_t endpoint_name[NODE_NAME_LENGTH];             // our NSP NODE name
+    
+    DBG("Starting BLE Advertising (%s)...\r\n",endpoint_name);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_REMOTE_CONTROL);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,(uint8_t *)endpoint_name,strlen((char *)endpoint_name));
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(1600); /* 1000ms; in multiples of 0.625ms. */
+    ble.startAdvertising();
+}
+
+// BLE send data
+int ble_send_data(uint8_t *data,int data_len,bool sendHeader)
+{
+    int sent = 0;
+    DBG("in ble_send_data() data_len=%d data: [",data_len);
+    for(int i=0;i<data_len;++i) {
+        DBG("%.2x",data[i]);
+        if (i < (data_len-1)) DBG(" ");
+    }
+    DBG("] sent: ");
+    
+    if (sendHeader) {
+        char header[10];
+        uint8_t buffer[1024];
+        
+        memset(header,0,10);
+        memset(buffer,0,1024);
+        
+        Base64 encoder;
+        int b64_data_len = 1024;    // initial sizing for malloc() in Base64...
+        char *b64_data = encoder.Encode((char *)data,data_len,(std::size_t *)&b64_data_len);
+        sprintf(header,"%d|",b64_data_len);
+        int header_length = strlen(header);
+        memcpy(buffer,header,header_length);
+        memcpy((buffer+header_length),b64_data,b64_data_len);
+        if (uart != NULL) {
+            DBG("Output: [%s] length=%d...",buffer,(header_length+b64_data_len));
+            
+            // SPLIT
+            SplitterAssembler splitter;
+            int num_fragments = splitter.split(buffer,header_length+b64_data_len);
+            sent = 0;
+            for(int i=0;i<num_fragments;++i) {
+                sent += uart->write((const void *)splitter.get(i),strlen((char *)splitter.get(i)));
+            }
+            uart->write("\n",strlen("\n"));
+        }
+        if (b64_data != NULL) free(b64_data);
+    }
+    else {
+        // plumbing headers are simple and dont need the data length header...
+        if (uart != NULL) {
+            sent = uart->write((const void *)data,data_len);
+            uart->write("\n",strlen("\n"));
+        }
+    }
+    
+    DBG("%d bytes\r\n",sent);
+    return sent;
+}
+
+// BLE recv data
+int ble_recv_data(uint8_t *buffer,int buffer_len)
+{
+    int received = 0;
+    memset(buffer,0,buffer_len);
+    if (uart != NULL) received = uart->read(buffer,buffer_len);
+    DBG("in ble_recv_data() buffer_len=%d buffer: [",buffer_len);
+    for(int i=0;i<received;++i) {
+        DBG("%.2x",buffer[i]);
+        if (i < (received-1)) DBG(" ");
+    }
+    DBG("] received %d bytes\r\n",received);
+    
+    // return the recieved number of bytes
+    return received;
+}
+    
 // plumb out the network
 void net_stubs_pre_plumb_network(bool canActAsRouterNode) 
 {
-    // we have to defer all Ethernet until we are configured..
-    ;
+    // BLE initialize...
+    DBG("Initializing BLE layer...\r\n");
+    ble_init();
 }
 
 // called after the endpoint is configured...
 void net_stubs_post_plumb_network(void) 
 {
+    // BLE advertise...
+    DBG("Beginning BLE advertising...\r\n");
+    ble_begin_advertising();
+    
+    // Attach the BLE UART Service
+    if (uart == NULL) uart = new UARTService(ble);
 }
 
 // create a suitable main event loop for this specific network
 void net_stubs_create_main_loop(void)
 {
-   // nothing to do for Ethernet endpoints - we are using the Threaded loop in nsdl_support.cpp
+   // nothing to do for BLE endpoints - we are using the Ticker-based loop in nsdl_support.cpp
    ; 
 }
 
 // register the endpoint
 void net_stubs_register_endpoint(void)
 {
-    // NSP registration
-    DBG("net_stubs_register_endpoint: calling NSP registration...\r\n");
-    register_endpoint(true);
-    DBG("net_stubs_register_endpoint: NSP registration completed\r\n");
+    // not used.. must wait until we get a BLE connect callback.. then register...
+    ;
 }
 
 // begin the main loop for processing network events
 void net_stubs_begin_main_loop(void) 
 {
     // NDSL main loop
+    DBG("Beginning NSDL Main Event Loop...\r\n");
     nsdl_event_loop();
 }
 
--- a/network_stubs/network_stubs.h	Wed Feb 11 23:01:05 2015 +0000
+++ b/network_stubs/network_stubs.h	Sat Feb 14 07:36:17 2015 +0000
@@ -1,6 +1,6 @@
 /**
  * @file    network_stubs.h
- * @brief   mbed Endpoint Network Stubs header (Ethernet)
+ * @brief   mbed Endpoint Network Stubs header (BLE)
  * @author  Doug Anson
  * @version 1.0
  * @see     
@@ -19,8 +19,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef __BT_STUBS_H__
-#define __BT_STUBS_H__
+#ifndef __BLE_STUBS_H__
+#define __BLE_STUBS_H__
 
 // mbed support
 #include "mbed.h"
@@ -39,6 +39,9 @@
 
 #include "mbed.h"
 
+#define MAX_CONNECTION_RECORD_LENGTH    64
+#define IP_ADDRESS_LENGTH               130
+
 // timeval
 struct timeval {
     uint32_t tv_sec;
@@ -49,4 +52,4 @@
 // socket length is simply an unsigned int.
 typedef uint32_t socklen_t;
 
-#endif // __BT_STUBS_H__
\ No newline at end of file
+#endif // __BLE_STUBS_H__
\ No newline at end of file