init
This commit is contained in:
		
							
								
								
									
										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 | ||||
		Reference in New Issue
	
	Block a user