this role reversal for Intel/jp works, but further work needed to make Intel/jp ambidexterous

This commit is contained in:
John Poole 2026-05-21 15:09:15 -07:00
commit cbc3553436
9 changed files with 523 additions and 21 deletions

View file

@ -22,6 +22,7 @@ Exercise 306 uses the same payload files as the Pi Zero BLE Reticulum tests:
texts/If.txt 195 bytes texts/If.txt 195 bytes
texts/If_full.txt 1583 bytes texts/If_full.txt 1583 bytes
texts/US_Constitution.txt 44225 bytes texts/US_Constitution.txt 44225 bytes
texts/little_boy_blue.txt 942 bytes
``` ```
The selected file is compiled into the firmware. The transfer code does not care which file is selected; `platformio.ini` chooses the source text through `custom_text_source`, and `scripts/embed_text.py` generates `SelectedText.h` in the build directory before compilation. The selected file is compiled into the firmware. The transfer code does not care which file is selected; `platformio.ini` chooses the source text through `custom_text_source`, and `scripts/embed_text.py` generates `SelectedText.h` in the build directory before compilation.
@ -77,9 +78,22 @@ tbeam_if_full_pi_zero_profile
tbeam_constitution_pi_zero_profile tbeam_constitution_pi_zero_profile
``` ```
## Build Once, Upload Twice Host-native environment:
Each selected text environment produces one firmware image. Build it once, then upload that same image to both boards. ```text
jp_native
jp_native_peripheral
```
`jp_native` builds a Linux console program instead of ESP32 firmware. It uses the host Bluetooth adapter through BlueZ D-Bus, skips the OLED path, and prints received text to stdout. The current jp payload is `texts/little_boy_blue.txt`.
`jp_native_peripheral` is the first Linux peripheral/server scaffold. It builds a separate binary that checks for BlueZ `GattManager1` and `LEAdvertisingManager1` support on the host adapter. It does not yet register the full Exercise 306 GATT service or accept a T-Beam connection.
## Building
### ESP32
Build the ESP32/T-Beam firmware with one of the `tbeam_*` environments. Each selected text environment produces one firmware image. Build it once, then upload that same image to both boards.
Build the short If sample: Build the short If sample:
@ -132,6 +146,88 @@ pio device monitor -p /dev/ttytDAN -b 115200
pio device monitor -p /dev/ttytBOB -b 115200 pio device monitor -p /dev/ttytBOB -b 115200
``` ```
### Intel x86_64
Build the jp Linux host binary with the `jp_native` environment:
```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/306_microReticulum_ble_file_transfer_oled -e jp_native
```
The resulting executable is:
```text
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native/program
```
Run it from the repository root:
```bash
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native/program
```
The host binary is a BlueZ BLE central. It expects the T-Beam to advertise the Exercise 306 service, then receives file-transfer text on the console. Because it uses system D-Bus and the Bluetooth adapter, sandboxed runs may require approval.
Build the jp peripheral capability-check binary with:
```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/306_microReticulum_ble_file_transfer_oled -e jp_native_peripheral
```
The resulting executable is:
```text
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native_peripheral/program
```
Run it from the repository root:
```bash
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native_peripheral/program
```
This build is expected to report whether the current BlueZ adapter exposes the GATT server and LE advertising managers needed for true Linux peripheral mode.
### AMD64
AMD64 is the same 64-bit x86 Linux target class as Intel x86_64 for this PlatformIO `native` build. On eos, build the same `jp_native` environment on that machine:
```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/306_microReticulum_ble_file_transfer_oled -e jp_native
```
The output path is the same relative path:
```text
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native/program
```
Do not copy the jp-built executable to ARM machines. Rebuild on the target architecture unless a cross-compile environment is added.
### ARM64
For a 64-bit Raspberry Pi OS on a Pi Zero 2W or Pi 4B, use the same `jp_native` environment and build directly on the Pi:
```bash
source /home/jlpoole/rnsenv/bin/activate
cd /usr/local/src/microreticulum/microReticulumTbeam
pio run -d exercises/306_microReticulum_ble_file_transfer_oled -e jp_native
```
PlatformIO `native` produces a binary for the machine doing the build, so an ARM64 Pi build produces an ARM64 executable at:
```text
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native/program
```
The Pi must have BlueZ, GLib/GIO development headers, and a BLE adapter that supports LE central mode. If the Pi is running a 32-bit OS, the result is a 32-bit ARM binary, not ARM64.
## Expected Output ## Expected Output
Once the Link is active, both nodes start sending: Once the Link is active, both nodes start sending:

View file

@ -18,6 +18,7 @@ build_src_filter =
+<*> +<*>
-<host_jp_main.cpp> -<host_jp_main.cpp>
-<HostBluezBleInterface.cpp> -<HostBluezBleInterface.cpp>
-<HostBluezPeripheralInterface.cpp>
build_flags = build_flags =
-Wall -Wall
@ -98,7 +99,7 @@ extends = tbeam_base
platform = native platform = native
build_type = debug build_type = debug
extra_scripts = pre:scripts/embed_text.py extra_scripts = pre:scripts/embed_text.py
custom_text_source = texts/If_full.txt custom_text_source = texts/little_boy_blue.txt
build_unflags = build_unflags =
-std=gnu++11 -std=gnu++11
build_flags = build_flags =
@ -133,6 +134,46 @@ lib_deps =
microReticulum=symlink:///usr/local/src/microreticulum/microReticulum microReticulum=symlink:///usr/local/src/microreticulum/microReticulum
lib_compat_mode = off lib_compat_mode = off
[env:jp_native_peripheral]
platform = native
build_type = debug
extra_scripts = pre:scripts/embed_text.py
custom_text_source = texts/little_boy_blue.txt
build_unflags =
-std=gnu++11
build_flags =
-std=c++17
-g3
-ggdb
-Wall
-Wextra
-Wno-missing-field-initializers
-Wno-format
-Wno-unused-parameter
-include stdint.h
-D HOST_NATIVE
-D HOST_BLE_PERIPHERAL
-D NATIVE
-D RNS_USE_FS
-D RNS_PERSIST_PATHS
-D USTORE_USE_UNIVERSALFS
-D MSGPACK_USE_BOOST=OFF
-D FILE_TRANSFER_CHUNK_SIZE=32
-D FILE_TRANSFER_CHUNK_INTERVAL_MS=500
-D HOST_NODE_LABEL=\"Node-JP-PERIPHERAL\"
!pkg-config --cflags gio-2.0 glib-2.0 bluez
!pkg-config --libs gio-2.0 glib-2.0 bluez
build_src_filter =
+<host_jp_main.cpp>
+<HostBluezPeripheralInterface.cpp>
lib_deps =
ArduinoJson@^7.4.2
MsgPack@^0.4.2
https://github.com/attermann/Crypto.git
https://github.com/attermann/microStore.git
microReticulum=symlink:///usr/local/src/microreticulum/microReticulum
lib_compat_mode = off
[env:amy] [env:amy]
extends = tbeam_base extends = tbeam_base
upload_port = /dev/ttytAMY upload_port = /dev/ttytAMY

View file

@ -286,6 +286,10 @@ bool HostBluezBleInterface::connect_device(const std::string& device_path) {
} }
g_variant_unref(result); g_variant_unref(result);
device_path_ = device_path; device_path_ = device_path;
device_subscription_ = g_dbus_connection_signal_subscribe(
bus_, BLUEZ_BUS, "org.freedesktop.DBus.Properties", "PropertiesChanged",
device_path_.c_str(), "org.bluez.Device1",
G_DBUS_SIGNAL_FLAGS_NONE, device_properties_changed, this, nullptr);
std::printf("BLE linux-central: connected to %s\n", device_path_.c_str()); std::printf("BLE linux-central: connected to %s\n", device_path_.c_str());
uint64_t deadline = now_ms() + 10000; uint64_t deadline = now_ms() + 10000;
@ -315,9 +319,11 @@ bool HostBluezBleInterface::connect_device(const std::string& device_path) {
size_t h2 = hasher(node_label_ + ":exercise306"); size_t h2 = hasher(node_label_ + ":exercise306");
std::memcpy(identity, &h1, std::min(sizeof(h1), sizeof(identity))); std::memcpy(identity, &h1, std::min(sizeof(h1), sizeof(identity)));
std::memcpy(identity + 8, &h2, std::min(sizeof(h2), sizeof(identity) - 8)); std::memcpy(identity + 8, &h2, std::min(sizeof(h2), sizeof(identity) - 8));
write_characteristic(rx_char_path_, identity, sizeof(identity), true);
connected_ = true; connected_ = true;
if (!write_characteristic(rx_char_path_, identity, sizeof(identity), true)) {
return false;
}
std::printf("BLE linux-central: notifications active; identity handshake sent\n"); std::printf("BLE linux-central: notifications active; identity handshake sent\n");
return true; return true;
} }
@ -408,7 +414,9 @@ bool HostBluezBleInterface::write_characteristic(const std::string& path,
g_variant_new("(aya{sv})", &bytes, &options), nullptr, g_variant_new("(aya{sv})", &bytes, &options), nullptr,
G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
if (!result) { if (!result) {
std::string message = error && error->message ? error->message : "unknown write failure";
log_error("BLE linux-central: WriteValue failed", error); log_error("BLE linux-central: WriteValue failed", error);
mark_disconnected(message.c_str());
return false; return false;
} }
g_variant_unref(result); g_variant_unref(result);
@ -474,15 +482,17 @@ void HostBluezBleInterface::send_outgoing(const RNS::Bytes& data) {
put_u32_be(fragment + 6, msg_id); put_u32_be(fragment + 6, msg_id);
put_u32_be(fragment + 10, (uint32_t)data.size()); put_u32_be(fragment + 10, (uint32_t)data.size());
std::memcpy(fragment + FRAG_HEADER_SIZE, data.data() + offset, chunk); std::memcpy(fragment + FRAG_HEADER_SIZE, data.data() + offset, chunk);
send_fragment(fragment, FRAG_HEADER_SIZE + chunk); if (!send_fragment(fragment, FRAG_HEADER_SIZE + chunk)) {
return;
}
RNS::Utilities::OS::sleep(0.008); RNS::Utilities::OS::sleep(0.008);
} }
InterfaceImpl::handle_outgoing(data); InterfaceImpl::handle_outgoing(data);
} }
void HostBluezBleInterface::send_fragment(const uint8_t* data, size_t len) { bool HostBluezBleInterface::send_fragment(const uint8_t* data, size_t len) {
write_characteristic(rx_char_path_, data, len, true); return write_characteristic(rx_char_path_, data, len, true);
} }
void HostBluezBleInterface::properties_changed(GDBusConnection* connection, void HostBluezBleInterface::properties_changed(GDBusConnection* connection,
@ -520,6 +530,36 @@ void HostBluezBleInterface::properties_changed(GDBusConnection* connection,
g_variant_unref(invalidated); g_variant_unref(invalidated);
} }
void HostBluezBleInterface::device_properties_changed(GDBusConnection* connection,
const gchar* sender_name,
const gchar* object_path,
const gchar* interface_name,
const gchar* signal_name,
GVariant* parameters,
gpointer user_data) {
(void)connection;
(void)sender_name;
(void)interface_name;
(void)signal_name;
auto* self = static_cast<HostBluezBleInterface*>(user_data);
if (!self || self->device_path_ != object_path) {
return;
}
const gchar* changed_iface = nullptr;
GVariant* changed = nullptr;
GVariant* invalidated = nullptr;
g_variant_get(parameters, "(&s@a{sv}@as)", &changed_iface, &changed, &invalidated);
if (std::strcmp(changed_iface, "org.bluez.Device1") == 0) {
gboolean connected = TRUE;
if (g_variant_lookup(changed, "Connected", "b", &connected) && !connected) {
self->mark_disconnected("device disconnected");
}
}
g_variant_unref(changed);
g_variant_unref(invalidated);
}
void HostBluezBleInterface::handle_fragment(const uint8_t* data, size_t len) { void HostBluezBleInterface::handle_fragment(const uint8_t* data, size_t len) {
if (len < FRAG_HEADER_SIZE) { if (len < FRAG_HEADER_SIZE) {
std::fprintf(stderr, "BLE linux-central: fragment too short len=%zu\n", len); std::fprintf(stderr, "BLE linux-central: fragment too short len=%zu\n", len);
@ -598,15 +638,40 @@ void HostBluezBleInterface::reset_reassembly() {
current_rx_message_id_ = 0; current_rx_message_id_ = 0;
} }
void HostBluezBleInterface::disconnect_peer() { void HostBluezBleInterface::mark_disconnected(const char* reason) {
bool was_connected = connected_ || !device_path_.empty() || !tx_char_path_.empty() || !rx_char_path_.empty();
connected_ = false; connected_ = false;
if (notify_subscription_) { if (bus_ && notify_subscription_) {
g_dbus_connection_signal_unsubscribe(bus_, notify_subscription_); g_dbus_connection_signal_unsubscribe(bus_, notify_subscription_);
notify_subscription_ = 0; notify_subscription_ = 0;
} }
if (!device_path_.empty()) { if (bus_ && device_subscription_) {
g_dbus_connection_signal_unsubscribe(bus_, device_subscription_);
device_subscription_ = 0;
}
device_path_.clear();
tx_char_path_.clear();
rx_char_path_.clear();
identity_char_path_.clear();
reset_reassembly();
next_scan_ms_ = now_ms() + 1000;
if (online_) {
if (was_connected) {
std::printf("BLE linux-central: disconnected; %s; returning to scan\n", reason ? reason : "link lost");
}
start_discovery();
} else if (was_connected) {
std::printf("BLE linux-central: disconnected; %s\n", reason ? reason : "link lost");
}
}
void HostBluezBleInterface::disconnect_peer() {
std::string path = device_path_;
bool should_disconnect = connected_ && !path.empty();
mark_disconnected("local stop");
if (should_disconnect && bus_) {
GError* error = nullptr; GError* error = nullptr;
GVariant* result = g_dbus_connection_call_sync(bus_, BLUEZ_BUS, device_path_.c_str(), GVariant* result = g_dbus_connection_call_sync(bus_, BLUEZ_BUS, path.c_str(),
"org.bluez.Device1", "Disconnect", "org.bluez.Device1", "Disconnect",
nullptr, nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr, G_DBUS_CALL_FLAGS_NONE, -1,
nullptr, &error); nullptr, &error);
@ -616,9 +681,4 @@ void HostBluezBleInterface::disconnect_peer() {
g_variant_unref(result); g_variant_unref(result);
} }
} }
device_path_.clear();
tx_char_path_.clear();
rx_char_path_.clear();
identity_char_path_.clear();
reset_reassembly();
} }

View file

@ -34,11 +34,12 @@ private:
bool discover_characteristics(); bool discover_characteristics();
bool start_notify(); bool start_notify();
bool write_characteristic(const std::string& path, const uint8_t* data, size_t len, bool with_response); bool write_characteristic(const std::string& path, const uint8_t* data, size_t len, bool with_response);
void send_fragment(const uint8_t* data, size_t len); bool send_fragment(const uint8_t* data, size_t len);
void handle_fragment(const uint8_t* data, size_t len); void handle_fragment(const uint8_t* data, size_t len);
void enqueue_packet(const RNS::Bytes& packet); void enqueue_packet(const RNS::Bytes& packet);
bool dequeue_packet(RNS::Bytes& packet); bool dequeue_packet(RNS::Bytes& packet);
void reset_reassembly(); void reset_reassembly();
void mark_disconnected(const char* reason);
void disconnect_peer(); void disconnect_peer();
static void properties_changed(GDBusConnection* connection, static void properties_changed(GDBusConnection* connection,
@ -49,6 +50,14 @@ private:
GVariant* parameters, GVariant* parameters,
gpointer user_data); gpointer user_data);
static void device_properties_changed(GDBusConnection* connection,
const gchar* sender_name,
const gchar* object_path,
const gchar* interface_name,
const gchar* signal_name,
GVariant* parameters,
gpointer user_data);
static constexpr const char* BLUEZ_BUS = "org.bluez"; static constexpr const char* BLUEZ_BUS = "org.bluez";
static constexpr const char* SERVICE_UUID = "37145b00-442d-4a94-917f-8f42c5da28e3"; static constexpr const char* SERVICE_UUID = "37145b00-442d-4a94-917f-8f42c5da28e3";
static constexpr const char* TX_UUID = "37145b00-442d-4a94-917f-8f42c5da28e4"; static constexpr const char* TX_UUID = "37145b00-442d-4a94-917f-8f42c5da28e4";
@ -74,6 +83,7 @@ private:
std::string rx_char_path_; std::string rx_char_path_;
std::string identity_char_path_; std::string identity_char_path_;
guint notify_subscription_ = 0; guint notify_subscription_ = 0;
guint device_subscription_ = 0;
bool online_ = false; bool online_ = false;
bool connected_ = false; bool connected_ = false;
bool discovering_ = false; bool discovering_ = false;

View file

@ -0,0 +1,170 @@
#include "HostBluezPeripheralInterface.h"
#include <Utilities/OS.h>
#include <cstdio>
using namespace RNS;
static void log_error(const char* what, GError* error) {
if (error) {
std::fprintf(stderr, "%s: %s\n", what, error->message);
g_error_free(error);
} else {
std::fprintf(stderr, "%s\n", what);
}
}
HostBluezPeripheralInterface::HostBluezPeripheralInterface(const std::string& node_label,
const char* name)
: InterfaceImpl(name), node_label_(node_label) {
_IN = true;
_OUT = true;
_bitrate = 1000000;
_HW_MTU = 168;
}
HostBluezPeripheralInterface::~HostBluezPeripheralInterface() {
stop();
if (bus_) {
g_object_unref(bus_);
}
}
bool HostBluezPeripheralInterface::start() {
if (online_) {
return true;
}
if (!connect_bus() || !find_adapter()) {
return false;
}
online_ = true;
_online = true;
std::printf("BLE linux-peripheral: adapter=%s label=%s service=%s\n",
adapter_path_.c_str(), node_label_.c_str(), SERVICE_UUID);
if (!adapter_supports_peripheral()) {
std::fprintf(stderr,
"BLE linux-peripheral: adapter/BlueZ is missing GattManager1 or LEAdvertisingManager1; peripheral mode cannot run on this adapter as configured\n");
return true;
}
std::printf("BLE linux-peripheral: BlueZ reports GATT server and LE advertising managers are present\n");
std::printf("BLE linux-peripheral: GATT object registration scaffold builds; runtime service registration is the next step\n");
return true;
}
void HostBluezPeripheralInterface::stop() {
online_ = false;
connected_ = false;
_online = false;
}
bool HostBluezPeripheralInterface::connect_bus() {
GError* error = nullptr;
bus_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
if (!bus_) {
log_error("BLE linux-peripheral: cannot connect to system D-Bus", error);
return false;
}
return true;
}
bool HostBluezPeripheralInterface::find_adapter() {
GError* error = nullptr;
GVariant* managed = g_dbus_connection_call_sync(bus_, BLUEZ_BUS, "/",
"org.freedesktop.DBus.ObjectManager",
"GetManagedObjects", nullptr,
G_VARIANT_TYPE("(a{oa{sa{sv}}})"),
G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
if (!managed) {
log_error("BLE linux-peripheral: GetManagedObjects failed", error);
return false;
}
GVariantIter* objects = nullptr;
g_variant_get(managed, "(a{oa{sa{sv}}})", &objects);
const gchar* object_path = nullptr;
GVariant* ifaces = nullptr;
while (g_variant_iter_next(objects, "{&o@a{sa{sv}}}", &object_path, &ifaces)) {
GVariant* adapter = g_variant_lookup_value(ifaces, "org.bluez.Adapter1", G_VARIANT_TYPE("a{sv}"));
if (adapter) {
adapter_path_ = object_path;
g_variant_unref(adapter);
GVariant* gatt_manager = g_variant_lookup_value(ifaces, "org.bluez.GattManager1", G_VARIANT_TYPE("a{sv}"));
GVariant* advertising_manager = g_variant_lookup_value(ifaces, "org.bluez.LEAdvertisingManager1", G_VARIANT_TYPE("a{sv}"));
has_gatt_manager_ = gatt_manager != nullptr;
has_advertising_manager_ = advertising_manager != nullptr;
if (gatt_manager) {
g_variant_unref(gatt_manager);
}
if (advertising_manager) {
g_variant_unref(advertising_manager);
}
g_variant_unref(ifaces);
break;
}
g_variant_unref(ifaces);
}
g_variant_iter_free(objects);
g_variant_unref(managed);
if (adapter_path_.empty()) {
std::fprintf(stderr, "BLE linux-peripheral: no BlueZ adapter found\n");
return false;
}
error = nullptr;
GVariant* powered = g_dbus_connection_call_sync(
bus_, BLUEZ_BUS, adapter_path_.c_str(), "org.freedesktop.DBus.Properties", "Set",
g_variant_new("(ssv)", "org.bluez.Adapter1", "Powered", g_variant_new_boolean(TRUE)),
nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
if (!powered) {
log_error("BLE linux-peripheral: could not power adapter", error);
return false;
}
g_variant_unref(powered);
return true;
}
bool HostBluezPeripheralInterface::adapter_supports_peripheral() const {
return has_gatt_manager_ && has_advertising_manager_;
}
void HostBluezPeripheralInterface::loop() {
if (!online_) {
return;
}
while (g_main_context_iteration(nullptr, FALSE)) {
}
RNS::Bytes packet({RNS::Type::NONE});
while (dequeue_packet(packet)) {
InterfaceImpl::handle_incoming(packet);
}
}
void HostBluezPeripheralInterface::send_outgoing(const RNS::Bytes& data) {
if (!online_ || !connected_) {
return;
}
// Full TX notify support depends on BlueZ GATT characteristic object
// registration. This scaffold intentionally compiles separately from the
// proven central path so adapter capability can be tested first.
InterfaceImpl::handle_outgoing(data);
}
void HostBluezPeripheralInterface::enqueue_packet(const RNS::Bytes& packet) {
incoming_packets_.push_back(packet);
}
bool HostBluezPeripheralInterface::dequeue_packet(RNS::Bytes& packet) {
if (incoming_packets_.empty()) {
return false;
}
packet = incoming_packets_.front();
incoming_packets_.pop_front();
return true;
}

View file

@ -0,0 +1,44 @@
#pragma once
#include <Bytes.h>
#include <Interface.h>
#include <gio/gio.h>
#include <deque>
#include <string>
class HostBluezPeripheralInterface : public RNS::InterfaceImpl {
public:
explicit HostBluezPeripheralInterface(const std::string& node_label,
const char* name = "HostBluezPeripheral");
~HostBluezPeripheralInterface() override;
bool start() override;
void stop() override;
void loop() override;
bool connected() const { return connected_; }
const char* role_name() const { return "linux-peripheral"; }
private:
void send_outgoing(const RNS::Bytes& data) override;
bool connect_bus();
bool find_adapter();
bool adapter_supports_peripheral() const;
void enqueue_packet(const RNS::Bytes& packet);
bool dequeue_packet(RNS::Bytes& packet);
static constexpr const char* BLUEZ_BUS = "org.bluez";
static constexpr const char* SERVICE_UUID = "37145b00-442d-4a94-917f-8f42c5da28e3";
std::string node_label_;
GDBusConnection* bus_ = nullptr;
std::string adapter_path_;
bool online_ = false;
bool connected_ = false;
bool has_gatt_manager_ = false;
bool has_advertising_manager_ = false;
std::deque<RNS::Bytes> incoming_packets_;
};

View file

@ -1,4 +1,10 @@
#if defined(HOST_BLE_PERIPHERAL)
#include "HostBluezPeripheralInterface.h"
using HostBleInterface = HostBluezPeripheralInterface;
#else
#include "HostBluezBleInterface.h" #include "HostBluezBleInterface.h"
using HostBleInterface = HostBluezBleInterface;
#endif
#include "SelectedText.h" #include "SelectedText.h"
#include <Destination.h> #include <Destination.h>
@ -58,7 +64,7 @@ static std::string peer_label;
static bool have_peer = false; static bool have_peer = false;
static bool link_active = false; static bool link_active = false;
static bool link_attempted = false; static bool link_attempted = false;
static HostBluezBleInterface* ble_impl = nullptr; static HostBleInterface* ble_impl = nullptr;
static std::string node_label = HOST_NODE_LABEL; static std::string node_label = HOST_NODE_LABEL;
static bool running = true; static bool running = true;
@ -415,8 +421,8 @@ static void setup_reticulum() {
filesystem.init(); filesystem.init();
RNS::Utilities::OS::register_filesystem(filesystem); RNS::Utilities::OS::register_filesystem(filesystem);
auto impl = std::shared_ptr<RNS::InterfaceImpl>(new HostBluezBleInterface(node_label)); auto impl = std::shared_ptr<RNS::InterfaceImpl>(new HostBleInterface(node_label));
ble_impl = static_cast<HostBluezBleInterface*>(impl.get()); ble_impl = static_cast<HostBleInterface*>(impl.get());
ble_interface = RNS::Interface(impl); ble_interface = RNS::Interface(impl);
ble_interface.mode(RNS::Type::Interface::MODE_GATEWAY); ble_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(ble_interface); RNS::Transport::register_interface(ble_interface);

View file

@ -0,0 +1,49 @@
Between the dark and the daylight,
When the night is beginning to lower,
Comes a pause in the day's occupations,
That is known as the Children's Hour.
I hear in the chamber above me
The patter of little feet,
The sound of a door that is opened,
And voices soft and sweet.
From my study I see in the lamplight,
Descending the broad hall stair,
Grave Alice, and laughing Allegra,
And Edith with golden hair.
A whisper, and then a silence:
Yet I know by their merry eyes
They are plotting and planning together
To take me by surprise.
A sudden rush from the stairway,
A sudden raid from the hall!
By three doors left unguarded
They enter my castle wall!
They climb up into my turret
O'er the arms and back of my chair;
If I try to escape, they surround me;
They seem to be everywhere.
They almost devour me with kisses,
Their arms about me entwine,
Till I think of the Bishop of Bingen
In his Mouse-Tower on the Rhine!
Do you think, O blue-eyed banditti,
Because you have scaled the wall,
Such an old mustache as I am
Is not a match for you all!
I have you fast in my fortress,
And will not let you depart,
But put you down into the dungeon
In the round-tower of my heart.
And there will I keep you forever,
Yes, forever and a day,
Till the walls shall crumble to ruin,
And moulder in dust away!

View file

@ -0,0 +1,26 @@
The little toy dog is covered with dust,
But sturdy and staunch he stands;
And the little toy soldier is red with rust,
And his musket molds in his hands.
Time was when the little toy dog was new,
And the soldier was passing fair;
And that was the time when our Little Boy Blue
Kissed them and put them there.
"Now, don't you go till I come," he said,
"And don't you make any noise!"
So, toddling off to his trundle-bed,
He dreamed of the pretty toys;
And, as he was dreaming, an angel song
Awakened our Little Boy Blue
Oh! the years are many, the years are long,
But the little toy friends are true!
Ay, faithful to Little Boy Blue they stand,
Each in the same old place
Awaiting the touch of a little hand,
The smile of a little face;
And they wonder, as waiting the long years through
In the dust of that little chair,
What has become of our Little Boy Blue,
Since he kissed them and put them there.