Skip to content

Commit

Permalink
Add BLE service classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Xasin committed Aug 26, 2021
1 parent 6dadfdb commit 6e9afd2
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 6 deletions.
2 changes: 1 addition & 1 deletion ESP32/xnm-ble/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@


if(CONFIG_BT_NIMBLE_ENABLED)
set(srcs "host.cpp" "service.cpp" "battery_svc.cpp")
set(srcs "host.cpp" "service.cpp" "string_stream.cpp" "battery_svc.cpp")
endif()

idf_component_register(SRCS "${srcs}"
Expand Down
39 changes: 39 additions & 0 deletions ESP32/xnm-ble/UUIDs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

# XNM BLE UUID definitions

This document shall describe and outline the UUIDs
used and defined by the XNM BLE system.
It will give a short overview of the different services and their according characteristics, as well as the data type for each characteristic.

## UUID Form

All XNM UUIDs are of the form `xxxxxxxx-2049-7fa3-0b4d-aa9e10786e6d`.
This UUID was generated with a online random UUID generator, though it may be noted that the last three bytes spell 'xnm' in ASCII :>

Service numbers will all be of the form `xxxx0000-POSTFIX`. The appended zeroes are meant to fit the UUIDs of service-specific characteristics.

As such, the UUID format for characteristics is of `ssssxxxx-POSTFIX`, where `ssss` shall match the Service's UUID

## Service types

The following is a list of services defined by, and used in, the XNM library code. Only the first two bytes, matching the UUID format specified above, will be given.

### `0f00` Debug service
This service includes a number of characteristics that specific various debugging interfaces and channels that shall aid in the development and troubleshooting of ESP32 projects. It may be left out for production runs, and is meant as developer tool rather than user interface.

The following characteristics may be included in the debug service, with the note that they may be left out depending on settings:
- `0f00 0001` Debug Stream. This characteristic will stream the ESP32 log messages (ESP_LOGx). Each message will be null-terminated, and may be split across multiple BLE packets depending on MTU size. A BLE-Terminal app shall suffice to read out the messages.
- `0f00 0002` System info JSON. This characteristic will return a JSON string when read, containing system information. This may include:
- Free heap memory `heap` (in bytes)
- Network status/ping `ping` (in ms round-trip-time, may be ping to/from MQTT broker)
- WiFi RSSI/status `rssi`
- Battery level `bat` (in % full)

### `5050` XNM property point interface
This Service shall provide an interface to the internal "PropertyPoint" configuration. This system was designed to allow multi-connection reconfiguration of the ESP from sources such as HTTP, Websockets, MQTT and BLE simultaneously. It is a lightweight, JSON-Based protocol, and is thusly well suited for a variety of generic tasks.

For further documentation, see here (*Note: Add a link and describe PropP*).

The following characteristic is part of the PropertyPoint interface:

- `5050 0001` Property Point characteristic. This characteristic streams update data to the attached BLE device in the form of JSON packets. Each packet is null-terminated, and may be spread across multiple BLE notifications to stay within BLE MTU size. The user may also write to this characteristic to send `set` commands (with longer packets again being split and null-terminated), allowing full PropP access through BLE.
24 changes: 20 additions & 4 deletions ESP32/xnm-ble/include/xnm/ble.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@

#pragma once

#include "ble/host.h"
#include "ble/service.h"
#include "ble/services/battery_svc.h"
#include <vector>
#include <functional>
#include <string>

#define XNM_BLE_UUID(a, b, c, d) (ble_uuid128_t({ \
BLE_UUID_TYPE_128, \
{ \
'm', 'n', 'x', 0x10, 0x9e, 0xaa, \
0x4d, 0x0b, 0xa3, 0x7f, \
0x49, 0x20, \
d, c, a, b \
} \
}))

namespace XNM {
namespace BLE {
static const char *TAG = "xnm-ble";
}
}
}

#include "ble/host.h"
#include "ble/service.h"

#include "ble/services/battery_svc.h"
#include "ble/services/string_stream.h"
1 change: 0 additions & 1 deletion ESP32/xnm-ble/include/xnm/ble/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include <vector>

#include "esp_nimble_hci.h"
#include "host/ble_hs.h"

namespace XNM {
Expand Down
41 changes: 41 additions & 0 deletions ESP32/xnm-ble/include/xnm/ble/services/string_stream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

#pragma once

#include "../../ble.h"

namespace XNM {
namespace BLE {

static ble_uuid128_t strstream_chr_uuid =
XNM_BLE_UUID(0x00, 0x01, 0x00, 0x00);

static ble_uuid128_t logstream_srv_uuid =
XNM_BLE_UUID(0x0F, 0x00, 0x00, 0x01);

class StringStream : public Service {
private:
ble_uuid128_t chr_uuid;

std::vector<char> in_buffer;

uint16_t attr_handle;
ble_gatt_chr_def stream_chr[2];

static int strstream_fn(uint16_t conn_handle, uint16_t attr_handle, ble_gatt_access_ctxt *ctxt, void *arg);

public : StringStream(Server &server, ble_uuid128_t srv_uuid = logstream_srv_uuid, ble_uuid128_t chr_uuid = logstream_srv_uuid);

// Will send the given string over a BLE channel.
// The string may be "chopped" into subsections across multiple
// BLE packets to fit MTU restrictions, with the final
// packet being null-terminated.
void send_str(const char *string);

// Will be called once a full string packet has been received, i.e.
// the received packet ends in a zero.
// Zero-Termination will be included in the string!
std::function<void (std::vector<char> &&)> on_receive;
};

}
}
67 changes: 67 additions & 0 deletions ESP32/xnm-ble/string_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>

#include "include/xnm/ble/services/string_stream.h"

namespace XNM {
namespace BLE {

int StringStream::strstream_fn(uint16_t conn_handle, uint16_t attr_handle, ble_gatt_access_ctxt * ctxt, void *arg) {
assert(arg != nullptr);

auto obj = reinterpret_cast<StringStream*>(arg);

if(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
auto len = OS_MBUF_PKTLEN(ctxt->om);


auto prev_size = obj->in_buffer.size();
obj->in_buffer.resize(obj->in_buffer.size() + len);

ble_hs_mbuf_to_flat(ctxt->om, obj->in_buffer.data() + prev_size, len, nullptr);

if(*(obj->in_buffer.rbegin()) == 0) {
ESP_LOGD("xnmble_str", "Got string data %s", obj->in_buffer.data());

if(obj->on_receive)
obj->on_receive(std::forward<std::vector<char>>(obj->in_buffer));

obj->in_buffer.resize(0);
obj->in_buffer.reserve(255);
}
}

return 0;
}

StringStream::StringStream(Server &server, ble_uuid128_t srv_uuid, ble_uuid128_t chr_uuid) : Service(server),
chr_uuid(chr_uuid),
in_buffer(),
attr_handle(0),
stream_chr({
{
reinterpret_cast<ble_uuid_t*>(&this->chr_uuid),
strstream_fn, this,
nullptr,
BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY,
0,

&attr_handle
},
{ nullptr }
}) {

this->uuid.u128 = srv_uuid;
chr_pointer = stream_chr;
}

void StringStream::send_str(const char *str) {
if(attr_handle == 0)
return;

ble_gattc_notify_custom(0, attr_handle, ble_hs_mbuf_from_flat(str, strlen(str) + 1));
}

}
}

0 comments on commit 6e9afd2

Please sign in to comment.