Doug Anson / mbedEndpointNetwork_BLE

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Files at this revision

API Documentation at this revision

Comitter:
ansond
Date:
Wed Feb 18 06:58:01 2015 +0000
Parent:
8:65d3c97aab26
Child:
10:95122a4a80cb
Commit message:
updates - working

Changed in this revision

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/BleUartRPC/Dispatcher.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/BleUartRPC/Dispatcher.h Show annotated file Show diff for this revision Revisions of this file
bt_network/BleUartRPC/UartRPC.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/BleUartRPC/UartRPC.h Show annotated file Show diff for this revision Revisions of this file
bt_network/BleUartRPC/UartRPCFunctions.cpp Show annotated file Show diff for this revision Revisions of this file
bt_network/BleUartRPC/UartRPCFunctions.h 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/nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- a/NSDL/nsdl_support.cpp	Tue Feb 17 07:01:22 2015 +0000
+++ b/NSDL/nsdl_support.cpp	Wed Feb 18 06:58:01 2015 +0000
@@ -195,8 +195,9 @@
         // only process if we are registered and thus connected... otherwise ignore
         if (__registered == true) {
             DBG("NSP: waiting for data...\r\n");
+            memset(nsp_buffer,0,NSDL_BUFFER_LENGTH);
             int n = server.receiveFrom(from,nsp_buffer,NSDL_BUFFER_LENGTH);
-            if (n >= 0) {
+            if (n > 0) {
                 DBG("NSP: received %d bytes... processing..\r\n.",n);
                 sn_nsdl_process_coap((uint8_t*)nsp_buffer,n,&received_packet_address); 
             } 
--- a/bt_network/BLE_API.lib	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BLE_API.lib	Wed Feb 18 06:58:01 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/ansond/code/BLE_API/#7557d9455cd0
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#1956023d42fb
--- a/bt_network/BleUartRPC/Dispatcher.cpp	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/Dispatcher.cpp	Wed Feb 18 06:58:01 2015 +0000
@@ -22,8 +22,8 @@
  
  #include "Dispatcher.h"
  
- #include "SplitterAssembler.h"
- SplitterAssembler __splitter;
+ // forward declaration
+ extern "C" int ble_rpc_recv_data(uint8_t *buffer,int buffer_length);
  
  #ifdef DBG
     #undef DBG
@@ -31,11 +31,86 @@
  #define DBG  std::printf
  
  // constructor
- Dispatcher::Dispatcher(BLEDevice &ble) :  m_uart(ble) {
+ Dispatcher::Dispatcher(BLEDevice &ble) :  m_uart(ble), m_splitter(), m_splitter_count(0), m_splitter_index(0) {
+     ble.onDataWritten(this,&Dispatcher::onDataWritten);
+     ble.onDataSent(this,&Dispatcher::onDataSent);
+     memset(this->m_send_packet,0,MAX_PACKET_LENGTH+1);
+ }
+ 
+ void Dispatcher::onDataSent(unsigned count) {
+     DBG("onDataSent: count=%d\r\n",count);
+ }
+ 
+ void Dispatcher::onDataWritten(const GattCharacteristicWriteCBParams *params) {
+     int length = (int)params->len;
+     uint8_t *data = (uint8_t *)params->data;
+     bool send_ack = false;
+     DBG("onDataWritten: received: [%s] length=%d\r\n",data,length);
+     
+     if (strstr((char *)data,"ACK") == NULL) {
+         // process this input from the peer
+         ble_rpc_recv_data(data,length);
+         
+         // we received something... so send an ack
+         send_ack = true;
+     }
+     else {
+         // received an ACK so note it...
+         DBG("onDataWritten: received ACK (OK)... continuing...\r\n");
+     }
+     
+     // write the next segment (if any...)
+     this->uart_write(send_ack);
+ }
+ 
+ int Dispatcher::uart_write(bool send_ack) {
+     if (this->m_splitter_count > 0) {
+         int length = this->m_splitter.getSplitLength();        // fixed
+         int index = this->m_splitter_index;
+         if (index < (this->m_splitter_count-1)) {
+            // wont be partial length...
+            DBG("dispatcher(): sending %dth segment: [%s]\r\n",index,this->m_splitter.get(index));
+            this->uart_write(this->m_splitter.get(index),UART_SEGMENT_LENGTH);
+         }
+         else {
+            // partial length so we pad with spaces... 
+            uint8_t *tmp = this->m_splitter.get(index);
+            int padded_length = strlen((char *)tmp);
+            int diff = UART_SEGMENT_LENGTH-padded_length;
+            for(int j=0;j<diff;++j) memcpy((tmp+padded_length+j)," ",1);
+            padded_length = strlen((char *)tmp);
+            
+            // send the last segment which may be a partial length one...
+            DBG("dispatcher(): sending %dth segment: [%s] length: %d (padded %d)...\r\n",index,tmp,padded_length,diff);
+            this->uart_write(tmp,padded_length);
+         }
+         
+         // update splitter index
+         ++this->m_splitter_index;
+         
+         // note when we are done...
+         if (this->m_splitter_index == this->m_splitter_count) {
+             this->m_splitter_index = 0;
+             this->m_splitter_count = 0;
+             this->m_splitter.reset();
+         }
+         
+         // return the length
+         return length;
+     }
+     else if (send_ack) {
+        // just send and ack as we received something... 
+        return this->uart_write((uint8_t *)"ACK\n",4);
+     }
+     else {
+        // nothing to send
+        return 0;
+     }
  }
  
  int Dispatcher::uart_write(uint8_t *data,int data_length) {
-     return this->m_uart.write(data,data_length);
+     int length = this->m_uart.write(data,data_length);
+     return length;
  }
  
  // dispatch 
@@ -48,64 +123,15 @@
      
      // Split into chunks and pad the last one
      DBG("dispatcher(): splitting into segments for UART transmission...\r\n");
-     __splitter.reset();
-     int split_len = __splitter.split(this->m_send_packet,len);
-     
-     // MULTIPLE write/putc
-     char buf[20];
-     memset(buf,0,20);
-     sprintf(buf,"\n"); 
-     int num_written = 1;
-     for(int k=0;k<15 && num_written > 0 ;++k) {
-        sprintf(buf,"%2d\n",k);
-        DBG("dispatcher(): sending %d...\r\n",k);
-        //for(int d=0;d<3;++d) this->m_uart._putc(buf[d]);
-        this->uart_write((uint8_t *)buf,3);
-        wait_ms(500);   
-     }
-     if (num_written <= 0) DBG("dispatcher(): UART gave up...\r\n");
+     this->m_splitter.reset();
+     this->m_splitter_count = this->m_splitter.split(this->m_send_packet,len);
      
-     /* LONG
-     char buf[1024];
-     memset(buf,0,1024);
-     DBG("dispatcher(): sending initial...\r\n");
-     sprintf(buf,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz\n");
-     this->m_uart.write(buf,strlen(buf));
-     for(int k=0;k<10;++k) {
-         DBG("dispatcher(): sending %d...\r\n",k);
-         this->m_uart.write(buf,strlen(buf));
-         wait_ms(1000);
-     }
-     */
-     
-     return -1;
-     
-     // send the split segments over the UART
-     for(int i=0;i<split_len;++i) {
-         if (i < (split_len-1)) {
-            // wont be partial length...
-            DBG("dispatcher(): sending %dth segment: [%s]\r\n",i,__splitter.get(i));
-            this->uart_write(__splitter.get(i),UART_SEGMENT_LENGTH);
-         }
-         else {
-            // partial length so we pad with spaces... 
-            uint8_t *tmp = __splitter.get(i);
-            int padded_length = strlen((char *)tmp);
-            int diff = UART_SEGMENT_LENGTH-padded_length;
-            for(int j=0;j<diff;++j) memcpy((tmp+padded_length+j)," ",1);
-            padded_length = strlen((char *)tmp);
-            
-            // send the last segment which may be a partial length one...
-            DBG("dispatcher(): sending %dth segment: [%s] length: %d (padded %d)...\r\n",i,tmp,padded_length,diff);
-            this->uart_write(tmp,padded_length);
-            
-            // update sent amount
-            len += diff;
-         }
-     }
+     // send the first of the segments and wait for an ack...
+     this->m_splitter_index = 0;
+     this->uart_write();
     
      // return the number of bytes sent...
-     DBG("dispatcher(): send completed. sent %d bytes...\r\n",len);
+     DBG("dispatcher(): send started. sent %d bytes...\r\n",len);
      return len;
  }
  
--- a/bt_network/BleUartRPC/Dispatcher.h	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/Dispatcher.h	Wed Feb 18 06:58:01 2015 +0000
@@ -25,10 +25,11 @@
  
  #include "BLEDevice.h"
  #include "UARTService.h"
+ #include "SplitterAssembler.h"
   
- #define MAX_PACKET_LENGTH          256            // longest packet we will send
- #define MAX_ARGUMENT_LENGTH        256            // longest argument sent as parameter list
- #define MAX_RESULT_LENGTH          256            // longest result received 
+ #define MAX_PACKET_LENGTH          300            // longest packet we will send (aligns with 15x20 in SplitterAssembler)
+ #define MAX_ARGUMENT_LENGTH        300            // longest argument sent as parameter list (aligns with 15x20 in SplitterAssembler)
+ #define MAX_RESULT_LENGTH          300            // longest result received (aligns with 15x20 in SplitterAssembler)
  #define UART_SEGMENT_LENGTH        20             // BLE: max UART MTU (will trigger send immediately...)
  
  class Dispatcher {
@@ -51,12 +52,18 @@
         int dispatch(uint8_t fn_id,uint8_t *args,int args_length,uint8_t *response,int response_length);
         
      private:
-        int          uart_write(uint8_t *data,int data_length);
-        int          prepare_send_packet(uint8_t fn_id,uint8_t *args,int args_length);
+        void              onDataSent(unsigned count);
+        void              onDataWritten(const GattCharacteristicWriteCBParams *params);
         
-        uint8_t      m_send_packet[MAX_PACKET_LENGTH+1];
-
-        UARTService  m_uart;
+        int               uart_write(bool send_ack = false);
+        int               uart_write(uint8_t *data,int data_length);
+        int               prepare_send_packet(uint8_t fn_id,uint8_t *args,int args_length);
+        
+        uint8_t           m_send_packet[MAX_PACKET_LENGTH+1];
+        UARTService       m_uart;
+        SplitterAssembler m_splitter;
+        int               m_splitter_count;
+        int               m_splitter_index;
  };
  
  #endif // __RPC_DISPATCH_H__
\ No newline at end of file
--- a/bt_network/BleUartRPC/UartRPC.cpp	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/UartRPC.cpp	Wed Feb 18 06:58:01 2015 +0000
@@ -21,7 +21,7 @@
  */
  
  #include "UartRPC.h"
- 
+ #include "UartRPCFunctions.h"
  #include "Base64.h"
  
  #ifdef DBG
@@ -30,7 +30,10 @@
  #define DBG  std::printf
  
  // constructor
- UartRPC::UartRPC(BLEDevice &ble) : m_dispatcher(ble) {
+ UartRPC::UartRPC(BLEDevice &ble) : m_dispatcher(ble), m_recv_accumulator() {
+     this->m_recv_raw_data = NULL;
+     this->m_recv_raw_data_length = 0;
+     this->m_local_dispatch_available = false;
  }
  
  // dispatch RPC
@@ -39,11 +42,113 @@
      // serialize the variable arguments into a long string...
      va_list args;
      uint8_t buffer[MAX_ARGUMENT_LENGTH+1];
-     memset(buffer,0,sizeof(buffer));
+     memset(buffer,0,MAX_ARGUMENT_LENGTH+1);
      va_start(args, format);
      vsnprintf((char *)buffer,MAX_ARGUMENT_LENGTH,format,args);
      va_end(args);
           
      // dispatch now...
      return this->m_dispatcher.dispatch(fn_id,buffer,strlen((char *)buffer),response,response_length);
+ }
+ 
+ // dispatch locally
+ void UartRPC::dispatch() {
+     // assemble the argument buffer...
+     uint8_t buffer[MAX_RESULT_LENGTH+1];
+     memset(buffer,0,MAX_RESULT_LENGTH+1);
+     int length = this->m_recv_accumulator.assemble(buffer,MAX_RESULT_LENGTH);
+     
+     // DEBUG
+     DBG("UartRPC: dispatch(local): buffer [%s] length=%d\r\n",buffer,length);
+     
+     // parse the buffer
+     uint8_t base64_buffer[MAX_RESULT_LENGTH+1];
+     memset(base64_buffer,0,MAX_RESULT_LENGTH+1);
+     int fn_id = 0;
+     
+     // strip off head,tail and separator, replace with spaces
+     int final_length = 0;
+     for(int i=0;i<length && final_length == 0;++i) {
+         if (buffer[i] == '[') buffer[i] = ' ';
+         if (buffer[i] == '|') buffer[i] = ' ';
+         if (buffer[i] == ']') { buffer[i] = '\0'; final_length = i; }
+     }
+     
+     // scan over the two values
+     sscanf((char *)buffer,"%d %s",&fn_id,base64_buffer);
+     int base64_buffer_length = strlen((char *)base64_buffer);
+     
+     // DEBUG
+     DBG("UartRPC: dispatch(local): fn_id = 0x%.2x base64_buffer = [%s] length=%d\r\n",fn_id,base64_buffer,base64_buffer_length);
+     
+     // reset our local dispatch
+     DBG("UartRPC: dispatch(local): resetting...\r\n");
+     this->resetLocalDispatch();
+     
+     // decode the arguments and save off the local dispatch...
+     DBG("UartRPC: dispatch(local): base64 decoding...\r\n");
+     Base64 b64;
+     base64_buffer_length = final_length;
+     this->m_recv_raw_data = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length);
+     this->m_recv_raw_data_length = base64_buffer_length; // modified by Decode()....
+     
+     // invoke the appropriate function
+     DBG("UartRPC: dispatch(local): requested function ID: 0x%.2x...\r\n",fn_id);
+     switch(fn_id) {
+         case RECV_DATA_FN: {
+             // only RECV_DATA_FN is local... make it ready for retrieval and flag it as ready...
+             DBG("UartRPC: dispatch(local): RECV_DATA_FN length=%d buffer=[%s]\r\n",this->m_recv_raw_data_length,this->m_recv_raw_data);
+                     
+             // local dispatch is now ready...
+             this->m_local_dispatch_available = true;
+             break;
+         }
+         default: {
+             // all other function ID's are non-local
+             DBG("UartRPC: dispatch(local): ignoring non-local function call request (id=0x%.2x)...\r\n",fn_id);
+             this->resetLocalDispatch();
+             break;
+         }
+     }
+ }
+ 
+ // is a local dispatch (packet) available?
+ bool UartRPC::localDispatchAvailable() { return this->m_local_dispatch_available; };
+ 
+ // reset the local dispatch availability
+ void UartRPC::resetLocalDispatch() {
+     if (this->m_recv_raw_data != NULL) free(this->m_recv_raw_data);
+     this->m_recv_raw_data = NULL;
+     this->m_recv_raw_data_length = 0;
+     this->m_local_dispatch_available = false;
+ }
+ 
+ // transfer the local dispatch and reset
+ int UartRPC::retrieveLocalDispatch(uint8_t *buffer,int buffer_length) {
+     if (this->m_local_dispatch_available == true) {
+         // copy over the dispatch
+         memset(buffer,0,buffer_length);
+         int length = this->m_recv_raw_data_length;
+         if (length > buffer_length) {
+             DBG("UartRPC::retrieveLocalDispatch: WARNING: input buffer is too small (is %d bytes, needs to be %d bytes)...\r\n",buffer_length,length);
+             length = buffer_length;
+         }
+         memcpy(buffer,this->m_recv_raw_data,length);
+         
+         // now reset
+         this->resetLocalDispatch();
+         
+         // return the length
+         return length;
+     }
+     return 0;
+ }
+ 
+ // accumulate to dispatch locally... 
+ bool UartRPC::accumulate(uint8_t *buffer,int buffer_length) {     
+     // add to the accumulator
+     this->m_recv_accumulator.add(buffer,buffer_length);
+     
+     // determine if we have a completed packet by looking for the "tail"
+     return this->m_recv_accumulator.hasCollectedCharacter(']');
  }
\ No newline at end of file
--- a/bt_network/BleUartRPC/UartRPC.h	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/UartRPC.h	Wed Feb 18 06:58:01 2015 +0000
@@ -31,10 +31,24 @@
  class UartRPC {
     public:
         UartRPC(BLEDevice &ble);
-        int dispatch(uint8_t fn_id,uint8_t *response,int response_length,const char *format,...);
-    
-    private:
-        Dispatcher m_dispatcher;
+        
+        // remote dispatch
+        int               dispatch(uint8_t fn_id,uint8_t *response,int response_length,const char *format,...);
+        
+        // local accumulate and dispatch of packets
+        bool              accumulate(uint8_t *buffer,int buffer_length);
+        void              dispatch();
+        bool              localDispatchAvailable(void);
+        int               retrieveLocalDispatch(uint8_t *buffer,int buffer_length);
+   
+    private:       
+        void              resetLocalDispatch(void);
+        
+        Dispatcher        m_dispatcher;
+        SplitterAssembler m_recv_accumulator;
+        bool              m_local_dispatch_available;
+        char             *m_recv_raw_data;
+        int               m_recv_raw_data_length;
  };
  
  #endif // __UART_RPC_H__
\ No newline at end of file
--- a/bt_network/BleUartRPC/UartRPCFunctions.cpp	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/UartRPCFunctions.cpp	Wed Feb 18 06:58:01 2015 +0000
@@ -31,14 +31,6 @@
  #endif
  #define DBG  std::printf
  
- typedef enum {
-     SOCKET_OPEN_FN  = 0x01,
-     SOCKET_CLOSE_FN = 0x02,
-     SEND_DATA_FN    = 0x04,
-     RECV_DATA_FN    = 0x08,
-     NUM_FNs         = 4
- } FunctionIDs;
- 
  UartRPC *__rpc = NULL;
  
  void ble_rpc_init(BLEDevice &ble) 
@@ -89,28 +81,23 @@
      return sent_length;
  }
  
+ int ble_rpc_recv_packet(uint8_t *buffer,int buffer_length)
+ {
+     DBG("ble_rpc_recv_packet: checking for a local dispatch...\r\n");
+     if (__rpc->localDispatchAvailable()) { 
+        DBG("ble_rpc_recv_packet: local dispatch is ready. Retrieving...\r\n");
+        return __rpc->retrieveLocalDispatch(buffer,buffer_length);
+     }
+     return 0;
+ }
+ 
  int ble_rpc_recv_data(uint8_t *buffer,int buffer_length)
  {
-     /*
-     uint8_t base64_buffer[MAX_RESULT_LENGTH+1];
-     memset(base64_buffer,0,MAX_RESULT_LENGTH+1);
-     DBG("ble_rpc_recv_data: seeing if any data is available...\r\n");
-     int recv_length =__rpc->dispatch(RECV_DATA_FN,base64_buffer,MAX_RESULT_LENGTH,"%s","");
-     DBG("ble_rpc_recv_data: received %d bytes of data...\r\n",recv_length);
-     if (recv_length > 0) {
-         // success
-         Base64 b64;
-         int base64_length = buffer_length;
-         char *raw_buffer = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_length);
-         memcpy(buffer,raw_buffer,base64_length);
-         if (raw_buffer != NULL) free(raw_buffer);
-         return base64_length;
+     DBG("ble_rpc_recv_data: got data...\r\n");
+     if (__rpc->accumulate(buffer,buffer_length)) {
+         DBG("ble_rpc_recv_data: received entire packet.. dispatching locally...\r\n");
+         __rpc->dispatch();
      }
-     else {
-         // failure
-         DBG("ble_rpc_recv_data: dispatch() failed\r\n");
-     }
-     */
-     return -1;
+     return buffer_length;
  } 
  
\ No newline at end of file
--- a/bt_network/BleUartRPC/UartRPCFunctions.h	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/BleUartRPC/UartRPCFunctions.h	Wed Feb 18 06:58:01 2015 +0000
@@ -25,10 +25,19 @@
  
  #include "UartRPC.h"
  
+ typedef enum {
+     SOCKET_OPEN_FN  = 0x01,
+     SOCKET_CLOSE_FN = 0x02,
+     SEND_DATA_FN    = 0x04,
+     RECV_DATA_FN    = 0x08,
+     NUM_FNs         = 4
+ } FunctionIDs;
+ 
  extern "C" void ble_rpc_init(BLEDevice &ble);
  extern "C" bool ble_rpc_open_udp_socket(char *ip_address,int port);
  extern "C" bool ble_rpc_close_udp_socket(void);
  extern "C" int ble_rpc_send_data(uint8_t *data,int data_length);
+ extern "C" int ble_rpc_recv_packet(uint8_t *buffer,int buffer_length);
  extern "C" int ble_rpc_recv_data(uint8_t *buffer,int buffer_length);
  
  #endif // __UART_RPC_FUNCTIONS_H__
\ No newline at end of file
--- a/bt_network/Socket/UDPSocket.cpp	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/Socket/UDPSocket.cpp	Wed Feb 18 06:58:01 2015 +0000
@@ -45,7 +45,7 @@
     return ble_rpc_send_data((uint8_t *)packet,length);
 }
 
-// -1 if unsuccessful, else number of bytes received
+// 0 if nothing to receive, else number of bytes received
 int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length) {
-    return ble_rpc_recv_data((uint8_t *)buffer,length);
+    return ble_rpc_recv_packet((uint8_t *)buffer,length);
 }
--- a/bt_network/SplitterAssembler.lib	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/SplitterAssembler.lib	Wed Feb 18 06:58:01 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/ansond/code/SplitterAssembler/#b0dc0395174e
+http://developer.mbed.org/users/ansond/code/SplitterAssembler/#094ed29a8bf7
--- a/bt_network/nRF51822.lib	Tue Feb 17 07:01:22 2015 +0000
+++ b/bt_network/nRF51822.lib	Wed Feb 18 06:58:01 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/ansond/code/nRF51822/#144d13c6784d
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#0e7a9efee6d7