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 2:30f4a0dab604, committed 2015-02-14
- Comitter:
- ansond
- Date:
- Sat Feb 14 07:36:17 2015 +0000
- Parent:
- 1:faa02c5fd781
- Child:
- 3:0f1bb62ac043
- Commit message:
- updates
Changed in this revision
--- 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