eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit cdf7209c218e275763367d00fd55b25b3b1d56c9
parent 8e74d2221936e1ff03621fcd3276f24d4cd918a8
Author: Daniel Barlow <dan@telent.net>
Date:   Sun, 11 Jan 2026 20:20:00 +0000

rename project

Diffstat:
MREADME.md | 4++--
Mandroid-termux-client/shore.py | 12++++++------
Decu-esp32/src/wibble.rs | 219-------------------------------------------------------------------------------
Mecu-esp32/src/wifi.rs | 4++--
Mstreamclient.rb | 2+-
5 files changed, 11 insertions(+), 230 deletions(-)

diff --git a/README.md b/README.md @@ -1,4 +1,4 @@ -# ECU-logical +# Eculocate Read data from the K-line of a Honda motorbike ECU and publish it -using Bluetooth LE +using UDP over Wifi diff --git a/android-termux-client/shore.py b/android-termux-client/shore.py @@ -17,9 +17,9 @@ bytes_recorded = 0 started = False hosts = { - "eculogical.local" : None, - "eculogical2.local" : None, - "eculogical3.local" : None + "eculocate.local" : None, + "eculocate2.local" : None, + "eculocate3.local" : None } def output_pathname(): @@ -111,9 +111,9 @@ with tg.Connection() as c: instances = tg.LinearLayout(a) - add_host(a, "eculogical.local", instances) - add_host(a, "eculogical2.local", instances) - add_host(a, "eculogical3.local", instances) + add_host(a, "eculocate.local", instances) + add_host(a, "eculocate2.local", instances) + add_host(a, "eculocate3.local", instances) tg.Space(a, instances) diff --git a/ecu-esp32/src/wibble.rs b/ecu-esp32/src/wibble.rs @@ -1,219 +0,0 @@ -use embassy_time::Timer; -use trouble_host::prelude::*; -use esp_radio::ble::controller::BleConnector; -use log::{warn,info}; -use embassy_futures::join::join; -use embassy_futures::select::select; - - -/// Max number of connections -const CONNECTIONS_MAX: usize = 1; - -/// Max number of L2CAP channels. -const L2CAP_CHANNELS_MAX: usize = 2; // Signal + att - -// GATT Server definition -#[gatt_server] -struct Server { - battery_service: BatteryService, - engine_speed_service: EngineSpeedService, -} - -/// Battery service -#[gatt_service(uuid = service::BATTERY)] -struct BatteryService { - /// Battery Level - #[descriptor(uuid = descriptors::VALID_RANGE, read, value = [0, 100])] - #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "hello", read, value = "Battery Level")] - #[characteristic(uuid = characteristic::BATTERY_LEVEL, read, notify, value = 10)] - level: u8, - #[characteristic(uuid = "408813df-5dd4-1f87-ec11-cdb001100000", write, read, notify)] - status: bool, -} - -#[gatt_service(uuid = "e000adbf-3508-435b-9638-eaff1d5e7c7e")] -struct EngineSpeedService { - /// Battery Level - // #[descriptor(uuid = descriptors::VALID_RANGE, read, value = [0, 100])] - // #[descriptor(uuid = descriptors::MEASUREMENT_DESCRIPTION, name = "hello", read, value = "Battery Level")] - #[characteristic(uuid = characteristic::ROTATIONAL_SPEED, read, notify, value = 1200)] - rpm: i32, -} - - -pub async fn run_ble(peripheral : esp_hal::peripherals::BT<'_>) { - let radio_init = esp_radio::init().expect("Failed to initialize Wi-Fi/BLE controller"); - let connector = BleConnector::new(&radio_init, peripheral, Default::default()).expect("connector"); - let controller: ExternalController<_, 20> = ExternalController::new(connector); - - // Using a fixed "random" address can be useful for testing. In real scenarios, one would - // use e.g. the MAC 6 byte array as the address (how to get that varies by the platform). - let address: Address = Address::random([0xff, 0x8f, 0x1a, 0x05, 0xe4, 0xff]); - info!("Our address = {:?}", address); - - let mut resources: HostResources<DefaultPacketPool, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = HostResources::new(); - let stack = trouble_host::new(controller, &mut resources).set_random_address(address); - let Host { - mut peripheral, runner, .. - } = stack.build(); - - info!("Starting advertising and GATT service"); - let server = Server::new_with_config(GapConfig::Peripheral(PeripheralConfig { - name: "ECUlogical", - appearance: &appearance::power_device::GENERIC_POWER_DEVICE, - })) - .unwrap(); - - let _ = join( - ble_task(runner), - async { - loop { - match advertise("Trouble Example", &mut peripheral, &server).await { - Ok(conn) => { - // set up tasks when the connection is established to a central, so they don't run when no one is connected. - let a = gatt_events_task(&server, &conn); - let b = custom_task(&server, &conn, &stack); - // run until any task ends (usually because the connection has been closed), - // then return to advertising state. - select(a, b).await; - } - Err(e) => { - panic!("[adv] error: {:?}", e); - } - } - } - }) - .await; -} - -/// This is a background task that is required to run forever alongside any other BLE tasks. -/// -/// ## Alternative -/// -/// If you didn't require this to be generic for your application, you could statically spawn this with i.e. -/// -/// ```rust,ignore -/// -/// #[embassy_executor::task] -/// async fn ble_task(mut runner: Runner<'static, SoftdeviceController<'static>>) { -/// runner.run().await; -/// } -/// -/// spawner.must_spawn(ble_task(runner)); -/// ``` -async fn ble_task<C: Controller, P: PacketPool>(mut runner: Runner<'_, C, P>) { - loop { - if let Err(e) = runner.run().await { - panic!("[ble_task] error: {:?}", e); - } - } -} - -/// Stream Events until the connection closes. -/// -/// This function will handle the GATT events and process them. -/// This is how we interact with read and write requests. -async fn gatt_events_task<P: PacketPool>(server: &Server<'_>, conn: &GattConnection<'_, '_, P>) -> Result<(), Error> { - let level = server.battery_service.level; - let reason = loop { - match conn.next().await { - GattConnectionEvent::Disconnected { reason } => break reason, - GattConnectionEvent::Gatt { event } => { - match &event { - // are these clauses important? they don't do anything - // except log - GattEvent::Read(event) => { - if event.handle() == level.handle { - let value = server.get(&level); - info!("[gatt] Read Event to Level Characteristic: {:?}", value); - } - } - GattEvent::Write(event) => { - if event.handle() == level.handle { - info!("[gatt] Write Event to Level Characteristic: {:?}", event.data()); - } - } - _ => {} - }; - // This step is also performed at drop(), but writing it explicitly is necessary - // in order to ensure reply is sent. - match event.accept() { - Ok(reply) => reply.send().await, - Err(e) => warn!("[gatt] error sending response: {:?}", e), - }; - } - _ => {} // ignore other Gatt Connection Events - } - }; - info!("[gatt] disconnected: {:?}", reason); - Ok(()) -} - -/// Create an advertiser to use to connect to a BLE Central, and wait for it to connect. -async fn advertise<'values, 'server, C: Controller>( - name: &'values str, - peripheral: &mut Peripheral<'values, C, DefaultPacketPool>, - server: &'server Server<'values>, -) -> Result<GattConnection<'values, 'server, DefaultPacketPool>, BleHostError<C::Error>> { - let mut advertiser_data = [0; 31]; - let len = AdStructure::encode_slice( - &[ - AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), - AdStructure::ServiceUuids16(&[[0x0f, 0x18]]), - AdStructure::CompleteLocalName(name.as_bytes()), - ], - &mut advertiser_data[..], - )?; - let advertiser = peripheral - .advertise( - &Default::default(), - Advertisement::ConnectableScannableUndirected { - adv_data: &advertiser_data[..len], - scan_data: &[], - }, - ) - .await?; - info!("[adv] advertising"); - let conn = advertiser.accept().await?.with_attribute_server(server)?; - info!("[adv] connection established"); - Ok(conn) -} - -/// Example task to use the BLE notifier interface. -/// This task will notify the connected central of a counter value every 2 seconds. -/// It will also read the RSSI value every 2 seconds. -/// and will stop when the connection is closed by the central or an error occurs. -async fn custom_task<C: Controller, P: PacketPool>( - server: &Server<'_>, - conn: &GattConnection<'_, '_, P>, - stack: &Stack<'_, C, P>, -) { - let mut tick: u8 = 0; - let level = server.battery_service.level; - let rpm = server.engine_speed_service.rpm; - loop { - tick = tick.wrapping_add(1); - info!("[custom_task] notifying connection of tick {}", tick); - - // if the characteristic does not support notifications, - // this would return an error. Use `set` instead, in that case. - // See inline comments in trouble-host/src/attribute.rs around - // line 631 - - if level.notify(conn, &tick).await.is_err() { - info!("[custom_task] error notifying connection"); - break; - }; - // read RSSI (Received Signal Strength Indicator) of the connection. - if let Ok(rssi) = conn.raw().rssi(stack).await { - info!("[custom_task] RSSI: {:?}", rssi); - } else { - info!("[custom_task] error getting RSSI"); - break; - }; - let new_rpm = 1200 + 20 * i32::from(tick); - rpm.notify(conn, &new_rpm).await.expect("failed to notify"); - - Timer::after_secs(2).await; - } -} diff --git a/ecu-esp32/src/wifi.rs b/ecu-esp32/src/wifi.rs @@ -59,11 +59,11 @@ fn dns_records(my_ip_address: [u8;4], serial: Option<usize>) -> Vec<mdns::Resour let (hostname, ptr_name) = match serial { None => ( - String::from("eculogical.local"), + String::from("eculocate.local"), String::from("Bike._keihin._udp.local") ), Some(number) => ( - format!("eculogical{number}.local"), + format!("eculocate{number}.local"), format!("Bike ({number})._keihin._udp.local") ) }; diff --git a/streamclient.rb b/streamclient.rb @@ -6,7 +6,7 @@ def subscribe(interval, table, start, finish) [interval, "T", table, start, finish].pack("s>ACCC") end -sock.connect("eculogical.local", 5000) +sock.connect("eculocate.local", 5000) sock.send(subscribe(500, 0x11, 0, 25), 0) finish = Time.now + 60