Before testing, but 3rd mode "dual" created for jp

This commit is contained in:
John Poole 2026-05-21 15:30:46 -07:00
commit 83b122df15
4 changed files with 157 additions and 10 deletions

3
.gitignore vendored
View file

@ -30,3 +30,6 @@ exercises/AMY.log
exercises/AMY_purged.log
exercises/examples/*
# Reticulum identify (secret) generatued when microReiticulum starts up if not alrady present
transport_identity

View file

@ -83,12 +83,15 @@ Host-native environment:
```text
jp_native
jp_native_peripheral
jp_native_dual
```
`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.
`jp_native_dual` registers both host interfaces in one process: the proven Linux central/client path and the current Linux peripheral/server scaffold. Today it can still use the central path to pair with a T-Beam, while also reporting whether BlueZ exposes the services needed for future host-native peripheral work.
## Building
### ESP32
@ -192,6 +195,28 @@ exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native_periphe
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.
Build the jp dual-role test 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_dual
```
The resulting executable is:
```text
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native_dual/program
```
Run it from the repository root:
```bash
exercises/306_microReticulum_ble_file_transfer_oled/.pio/build/jp_native_dual/program
```
For the current T-Beam test, start `jp_native` or `jp_native_dual` first and wait for `BLE linux-central: scanning for Reticulum service`, then RESET the T-Beam. The dual binary is not fully ambidextrous until the Linux peripheral/server scaffold registers the real GATT service and advertisement.
### 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:

View file

@ -174,6 +174,47 @@ lib_deps =
microReticulum=symlink:///usr/local/src/microreticulum/microReticulum
lib_compat_mode = off
[env:jp_native_dual]
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_DUAL
-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-DUAL\"
!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>
+<HostBluezBleInterface.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]
extends = tbeam_base
upload_port = /dev/ttytAMY

View file

@ -1,4 +1,7 @@
#if defined(HOST_BLE_PERIPHERAL)
#if defined(HOST_BLE_DUAL)
#include "HostBluezBleInterface.h"
#include "HostBluezPeripheralInterface.h"
#elif defined(HOST_BLE_PERIPHERAL)
#include "HostBluezPeripheralInterface.h"
using HostBleInterface = HostBluezPeripheralInterface;
#else
@ -24,7 +27,9 @@ using HostBleInterface = HostBluezBleInterface;
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
static constexpr const char* APP_NAME = "microreticulum";
static constexpr const char* APP_ASPECT = "filetransfer";
@ -53,7 +58,14 @@ static constexpr uint32_t FNV1A_OFFSET = 2166136261UL;
static constexpr uint32_t FNV1A_PRIME = 16777619UL;
static RNS::Reticulum reticulum({RNS::Type::NONE});
#if defined(HOST_BLE_DUAL)
static std::vector<RNS::Interface> ble_interfaces;
static HostBluezBleInterface* ble_central_impl = nullptr;
static HostBluezPeripheralInterface* ble_peripheral_impl = nullptr;
#else
static RNS::Interface ble_interface({RNS::Type::NONE});
static HostBleInterface* ble_impl = nullptr;
#endif
static RNS::Identity local_identity({RNS::Type::NONE});
static RNS::Destination inbound_destination({RNS::Type::NONE});
static RNS::Destination peer_destination({RNS::Type::NONE});
@ -64,7 +76,6 @@ static std::string peer_label;
static bool have_peer = false;
static bool link_active = false;
static bool link_attempted = false;
static HostBleInterface* ble_impl = nullptr;
static std::string node_label = HOST_NODE_LABEL;
static bool running = true;
@ -421,12 +432,30 @@ static void setup_reticulum() {
filesystem.init();
RNS::Utilities::OS::register_filesystem(filesystem);
#if defined(HOST_BLE_DUAL)
auto central = std::shared_ptr<RNS::InterfaceImpl>(new HostBluezBleInterface(node_label));
ble_central_impl = static_cast<HostBluezBleInterface*>(central.get());
RNS::Interface central_interface(central);
central_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(central_interface);
ble_interfaces.push_back(central_interface);
central_interface.start();
auto peripheral = std::shared_ptr<RNS::InterfaceImpl>(new HostBluezPeripheralInterface(node_label));
ble_peripheral_impl = static_cast<HostBluezPeripheralInterface*>(peripheral.get());
RNS::Interface peripheral_interface(peripheral);
peripheral_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(peripheral_interface);
ble_interfaces.push_back(peripheral_interface);
peripheral_interface.start();
#else
auto impl = std::shared_ptr<RNS::InterfaceImpl>(new HostBleInterface(node_label));
ble_impl = static_cast<HostBleInterface*>(impl.get());
ble_interface = RNS::Interface(impl);
ble_interface.mode(RNS::Type::Interface::MODE_GATEWAY);
RNS::Transport::register_interface(ble_interface);
ble_interface.start();
#endif
reticulum = RNS::Reticulum();
reticulum.transport_enabled(false);
@ -447,6 +476,59 @@ static void setup_reticulum() {
std::printf("Local SINGLE destination: %s\n", inbound_destination.hash().toHex().c_str());
}
static void loop_ble_interfaces() {
#if defined(HOST_BLE_DUAL)
if (ble_central_impl) {
ble_central_impl->loop();
}
if (ble_peripheral_impl) {
ble_peripheral_impl->loop();
}
#else
if (ble_impl) {
ble_impl->loop();
}
#endif
}
static bool ble_connected() {
#if defined(HOST_BLE_DUAL)
return (ble_central_impl && ble_central_impl->connected()) ||
(ble_peripheral_impl && ble_peripheral_impl->connected());
#else
return ble_impl && ble_impl->connected();
#endif
}
static const char* ble_role_status() {
#if defined(HOST_BLE_DUAL)
if (ble_central_impl && ble_central_impl->connected()) {
return ble_central_impl->role_name();
}
if (ble_peripheral_impl && ble_peripheral_impl->connected()) {
return ble_peripheral_impl->role_name();
}
return "linux-dual";
#else
return ble_impl ? ble_impl->role_name() : "unknown";
#endif
}
static void stop_ble_interfaces() {
#if defined(HOST_BLE_DUAL)
if (ble_peripheral_impl) {
ble_peripheral_impl->stop();
}
if (ble_central_impl) {
ble_central_impl->stop();
}
#else
if (ble_impl) {
ble_impl->stop();
}
#endif
}
static void handle_signal(int signal) {
(void)signal;
running = false;
@ -474,15 +556,13 @@ int main() {
while (running) {
reticulum.loop();
if (ble_impl) {
ble_impl->loop();
}
loop_ble_interfaces();
uint64_t now = millis64();
if (ble_impl && !ble_impl->connected()) {
if (!ble_connected()) {
if (next_wait_log_ms == 0 || now >= next_wait_log_ms) {
next_wait_log_ms = now + 10000;
std::printf("BLE %s waiting for peer\n", ble_impl->role_name());
std::printf("BLE %s waiting for peer\n", ble_role_status());
}
RNS::Utilities::OS::sleep(0.005);
continue;
@ -510,9 +590,7 @@ int main() {
RNS::Utilities::OS::sleep(0.005);
}
if (ble_impl) {
ble_impl->stop();
}
stop_ble_interfaces();
std::printf("\nStopped\n");
return 0;
}