init
This commit is contained in:
commit
7e2db36a8c
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
1017
Cargo.lock
generated
Normal file
1017
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "ble_server"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
btleplug = "*"
|
||||||
|
uuid = "*"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
futures ="*"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "ble_server"
|
||||||
|
path = "main.rs"
|
158
esp32-c3.ino
Normal file
158
esp32-c3.ino
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include <BLEDevice.h>
|
||||||
|
#include <BLEServer.h>
|
||||||
|
#include <BLEUtils.h>
|
||||||
|
#include <BLE2902.h>
|
||||||
|
#include "MPU6050.h"
|
||||||
|
#include "Wire.h"
|
||||||
|
|
||||||
|
#define SERVICE_UUID "9b9f77c6-7e68-4109-b987-b096233d9525"
|
||||||
|
#define CHARACTERISTIC_UUID "1ab2c9f4-19c0-48dd-8932-ed72558ec593"
|
||||||
|
|
||||||
|
MPU6050 accelgyro;
|
||||||
|
BLECharacteristic *pCharacteristic;
|
||||||
|
BLEServer *pServer;
|
||||||
|
bool deviceConnected = false;
|
||||||
|
|
||||||
|
int16_t ax, ay, az;
|
||||||
|
int16_t gx, gy, gz;
|
||||||
|
|
||||||
|
class MyServerCallbacks : public BLEServerCallbacks {
|
||||||
|
void onConnect(BLEServer *pServer) {
|
||||||
|
Serial.println("Device connected");
|
||||||
|
deviceConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(BLEServer *pServer) {
|
||||||
|
Serial.println("Device disconnected");
|
||||||
|
deviceConnected = false;
|
||||||
|
BLEDevice::startAdvertising(); // Restart advertising
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup_ble() {
|
||||||
|
BLEDevice::init("ESP32");
|
||||||
|
BLEServer *pServer = BLEDevice::createServer();
|
||||||
|
BLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
||||||
|
CHARACTERISTIC_UUID,
|
||||||
|
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
|
||||||
|
|
||||||
|
pService->start();
|
||||||
|
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
|
||||||
|
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
||||||
|
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||||
|
pAdvertising->setScanResponse(true);
|
||||||
|
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
|
||||||
|
pAdvertising->setMinPreferred(0x12);
|
||||||
|
|
||||||
|
uint8_t gyroData[] = { 1, 2, 3, 4, 5, 6 };
|
||||||
|
pCharacteristic->setValue(gyroData, sizeof(gyroData));
|
||||||
|
pCharacteristic->notify();
|
||||||
|
BLEDevice::startAdvertising();
|
||||||
|
Serial.println("Characteristic defined! Now you can read it in your phone!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Wire.begin();
|
||||||
|
|
||||||
|
// initialize serial communication
|
||||||
|
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
|
||||||
|
// it's really up to you depending on your project)
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// initialize device
|
||||||
|
Serial.println("Initializing I2C devices...");
|
||||||
|
accelgyro.initialize();
|
||||||
|
|
||||||
|
// verify connection
|
||||||
|
Serial.println("Testing device connections...");
|
||||||
|
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
|
||||||
|
|
||||||
|
// use the code below to change accel/gyro offset values
|
||||||
|
Serial.println("Updating internal sensor offsets...");
|
||||||
|
// -76 -2359 1688 0 0 0
|
||||||
|
Serial.print(accelgyro.getXAccelOffset());
|
||||||
|
Serial.print("\t"); // -76
|
||||||
|
Serial.print(accelgyro.getYAccelOffset());
|
||||||
|
Serial.print("\t"); // -2359
|
||||||
|
Serial.print(accelgyro.getZAccelOffset());
|
||||||
|
Serial.print("\t"); // 1688
|
||||||
|
Serial.print(accelgyro.getXGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print(accelgyro.getYGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print(accelgyro.getZGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print("\n");
|
||||||
|
accelgyro.setXGyroOffset(220);
|
||||||
|
accelgyro.setYGyroOffset(76);
|
||||||
|
accelgyro.setZGyroOffset(-85);
|
||||||
|
Serial.print(accelgyro.getXAccelOffset());
|
||||||
|
Serial.print("\t"); // -76
|
||||||
|
Serial.print(accelgyro.getYAccelOffset());
|
||||||
|
Serial.print("\t"); // -2359
|
||||||
|
Serial.print(accelgyro.getZAccelOffset());
|
||||||
|
Serial.print("\t"); // 1688
|
||||||
|
Serial.print(accelgyro.getXGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print(accelgyro.getYGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print(accelgyro.getZGyroOffset());
|
||||||
|
Serial.print("\t"); // 0
|
||||||
|
Serial.print("\n");
|
||||||
|
|
||||||
|
|
||||||
|
setup_ble();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// read raw accel/gyro measurements from device
|
||||||
|
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
|
||||||
|
|
||||||
|
// these methods (and a few others) are also available
|
||||||
|
//accelgyro.getAcceleration(&ax, &ay, &az);
|
||||||
|
//accelgyro.getRotation(&gx, &gy, &gz);
|
||||||
|
|
||||||
|
// display tab-separated accel/gyro x/y/z values
|
||||||
|
Serial.print("a/g:\t");
|
||||||
|
Serial.print(ax);
|
||||||
|
Serial.print("\t");
|
||||||
|
Serial.print(ay);
|
||||||
|
Serial.print("\t");
|
||||||
|
Serial.print(az);
|
||||||
|
Serial.print("\t");
|
||||||
|
Serial.print(gx);
|
||||||
|
Serial.print("\t");
|
||||||
|
Serial.print(gy);
|
||||||
|
Serial.print("\t");
|
||||||
|
Serial.println(gz);
|
||||||
|
|
||||||
|
if (deviceConnected) {
|
||||||
|
|
||||||
|
uint8_t encodedData[12];
|
||||||
|
|
||||||
|
encodedData[0] = static_cast<uint8_t>(ax & 0xFF);
|
||||||
|
encodedData[1] = static_cast<uint8_t>((ax >> 8) & 0xFF);
|
||||||
|
|
||||||
|
encodedData[2] = static_cast<uint8_t>(ay & 0xFF);
|
||||||
|
encodedData[3] = static_cast<uint8_t>((ay >> 8) & 0xFF);
|
||||||
|
|
||||||
|
encodedData[4] = static_cast<uint8_t>(az & 0xFF);
|
||||||
|
encodedData[5] = static_cast<uint8_t>((az >> 8) & 0xFF);
|
||||||
|
|
||||||
|
encodedData[6] = static_cast<uint8_t>(gx & 0xFF);
|
||||||
|
encodedData[7] = static_cast<uint8_t>((gx >> 8) & 0xFF);
|
||||||
|
|
||||||
|
encodedData[8] = static_cast<uint8_t>(gy & 0xFF);
|
||||||
|
encodedData[9] = static_cast<uint8_t>((gy >> 8) & 0xFF);
|
||||||
|
|
||||||
|
encodedData[10] = static_cast<uint8_t>(gz & 0xFF);
|
||||||
|
encodedData[11] = static_cast<uint8_t>((gz >> 8) & 0xFF);
|
||||||
|
|
||||||
|
pCharacteristic->setValue(encodedData, sizeof(encodedData));
|
||||||
|
pCharacteristic->notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
delay(50);
|
||||||
|
}
|
39
main.py
Normal file
39
main.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import asyncio
|
||||||
|
from bleak import BleakClient
|
||||||
|
|
||||||
|
# Specify the MAC address and service UUID
|
||||||
|
device_address = "64:E8:33:DA:A2:B6"
|
||||||
|
service_uuid = "9b9f77c6-7e68-4109-b987-b096233d9525"
|
||||||
|
characteristic_uuid = "1ab2c9f4-19c0-48dd-8932-ed72558ec593"
|
||||||
|
|
||||||
|
async def connect_to_ble_device(address, uuid):
|
||||||
|
async with BleakClient(address) as client:
|
||||||
|
print(f"Connected: {client.is_connected}")
|
||||||
|
|
||||||
|
# Discover services
|
||||||
|
services = await client.get_services()
|
||||||
|
for service in services:
|
||||||
|
if service.uuid.lower() == uuid.lower():
|
||||||
|
print(f"Found Service: {service.uuid}")
|
||||||
|
|
||||||
|
# You can further explore characteristics within the service if needed
|
||||||
|
for char in service.characteristics:
|
||||||
|
if char.uuid.lower() == characteristic_uuid.lower():
|
||||||
|
print(f"Found Characteristic: {char.uuid}")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# Read the value of the characteristic
|
||||||
|
value = await client.read_gatt_char(char.uuid)
|
||||||
|
integers = [int(byte) for byte in value]
|
||||||
|
print(f"Characteristic Value as Integers: {integers}")
|
||||||
|
|
||||||
|
# Wait for the specified interval
|
||||||
|
await asyncio.sleep(10 / 1000.0)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await connect_to_ble_device(device_address, service_uuid)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
95
main.rs
Normal file
95
main.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use btleplug::api::{Central, CharPropFlags, Manager as _, Peripheral, ScanFilter};
|
||||||
|
use btleplug::platform::Manager;
|
||||||
|
use futures::stream::StreamExt;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
const DEVICE_ADDR: &str = "64:E8:33:DA:A2:B6";
|
||||||
|
const NOTIFY_CHARACTERISTIC_UUID: Uuid = Uuid::from_u128(0x1ab2c9f4_19c0_48dd_8932_ed72558ec593);
|
||||||
|
|
||||||
|
async fn find_adapter() -> Result<impl Central, Box<dyn Error>> {
|
||||||
|
let manager = Manager::new().await?;
|
||||||
|
let adapters = manager.adapters().await?;
|
||||||
|
for adapter in adapters {
|
||||||
|
return Ok(adapter);
|
||||||
|
}
|
||||||
|
Err("No powered adapters found".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let adapter = find_adapter().await?;
|
||||||
|
|
||||||
|
println!("Starting scan...");
|
||||||
|
adapter
|
||||||
|
.start_scan(ScanFilter::default())
|
||||||
|
.await
|
||||||
|
.expect("Can't scan BLE adapter for connected devices...");
|
||||||
|
time::sleep(Duration::from_secs(2)).await;
|
||||||
|
let peripherals = adapter.peripherals().await?;
|
||||||
|
|
||||||
|
if peripherals.is_empty() {
|
||||||
|
eprintln!("->>> BLE peripheral devices were not found, sorry. Exiting...");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(esp32) = peripherals
|
||||||
|
.iter()
|
||||||
|
.find(|peripheral| peripheral.address().to_string() == DEVICE_ADDR)
|
||||||
|
{
|
||||||
|
let properties = esp32.properties().await?;
|
||||||
|
let is_connected = esp32.is_connected().await?;
|
||||||
|
// let address = esp32.address().to_string();
|
||||||
|
let local_name = properties
|
||||||
|
.unwrap()
|
||||||
|
.local_name
|
||||||
|
.unwrap_or(String::from("(peripheral name unknown)"));
|
||||||
|
|
||||||
|
println!("Found matching peripheral {:?}...", "ESP32");
|
||||||
|
if !is_connected {
|
||||||
|
// Connect if we aren't already connected.
|
||||||
|
if let Err(err) = esp32.connect().await {
|
||||||
|
eprintln!("Error connecting to peripheral, skipping: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let is_connected = esp32.is_connected().await?;
|
||||||
|
println!(
|
||||||
|
"Now connected ({:?}) to peripheral {:?}.",
|
||||||
|
is_connected, &local_name
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("Discover peripheral {:?} services...", local_name);
|
||||||
|
esp32.discover_services().await?;
|
||||||
|
for characteristic in esp32.characteristics() {
|
||||||
|
println!("Checking characteristic {:?}", characteristic);
|
||||||
|
// Subscribe to notifications from the characteristic with the selected
|
||||||
|
// UUID.
|
||||||
|
if characteristic.uuid == NOTIFY_CHARACTERISTIC_UUID
|
||||||
|
&& characteristic.properties.contains(CharPropFlags::NOTIFY)
|
||||||
|
{
|
||||||
|
println!("Subscribing to characteristic {:?}", characteristic.uuid);
|
||||||
|
esp32.subscribe(&characteristic).await?;
|
||||||
|
let mut notification_stream = esp32.notifications().await?;
|
||||||
|
let mut old_time = time::Instant::now();
|
||||||
|
while let Some(data) = notification_stream.next().await {
|
||||||
|
let delta = time::Instant::now() - old_time;
|
||||||
|
let delta_ms = delta.as_millis() as f64; // Convert Duration to milliseconds
|
||||||
|
let rounded_delta = (delta_ms * 10.0).round() / 10.0; // Round to one decimal place
|
||||||
|
println!(
|
||||||
|
"Received data from {:?} [{:?}ms]: {:?}",
|
||||||
|
local_name, rounded_delta, data.value
|
||||||
|
);
|
||||||
|
old_time = time::Instant::now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Disconnecting from peripheral {:?}...", local_name);
|
||||||
|
esp32.disconnect().await?;
|
||||||
|
} else {
|
||||||
|
println!("ESP Not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
2
sketch.yaml
Normal file
2
sketch.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
default_port: /dev/ttyACM0
|
||||||
|
default_fqbn: esp32:esp32:XIAO_ESP32C3
|
Loading…
Reference in New Issue
Block a user