Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler
Revision 9:bf0cf5828378, committed 2015-02-18
- 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
--- 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