Doug Anson / mbedEndpointNetwork_BLE

Dependencies:   libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler

Revision:
9:bf0cf5828378
Parent:
6:98af441fd960
Child:
11:d601b867b297
--- 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