Skip to content

Commit

Permalink
Finish BLE implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Meph1587 committed Jan 11, 2021
1 parent 5bd6b60 commit 9294690
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 248 deletions.
41 changes: 20 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
[package]
name = "streams-ble-gateway"
name = "ble-gateway"
version = "0.1.0"
authors = ["AleBuser <[email protected]>"]
edition = "2018"

[[bin]]
name="scan"
path="bin/scan.rs"

[lib]
name = "local"
path = "src/lib.rs"
Expand All @@ -21,6 +25,5 @@ rand = "0.7.3"
base64 = "^0.12"
blurz = "0.4.0"
regex = "1"
lazy_static = "1.4.0"
once_cell = "1.4.1"
btleplug = "0.5.4"
27 changes: 27 additions & 0 deletions bin/scan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use blurz::bluetooth_adapter::BluetoothAdapter;
use blurz::bluetooth_device::BluetoothDevice;
use blurz::bluetooth_discovery_session::BluetoothDiscoverySession;
use blurz::bluetooth_session::BluetoothSession;

fn main() -> () {
let session = &BluetoothSession::create_session(None).unwrap();
let adapter: BluetoothAdapter = BluetoothAdapter::init(session).unwrap();
let adapter_id = adapter.get_id();
let discover_session = BluetoothDiscoverySession::create_session(&session, adapter_id).unwrap();

discover_session.start_discovery().unwrap();
let devices = adapter.get_device_list().unwrap();
discover_session.stop_discovery().unwrap();

println!("Listing Surrounding Devices ...");
for device_path in devices {
let device = BluetoothDevice::new(session, device_path.to_string());
if let Ok(n) = device.get_name() {
println!(
"MAC Address:{:?} - Name: {:?} ",
device.get_address().unwrap(),
n,
);
}
}
}
10 changes: 3 additions & 7 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
{
"whitelisted_device_ids": [
"DEVICE_ID_1",
"DEVICE_ID_2"
"device_ids": [
"24:6F:28:8F:80:36"
],
"device_ble_name": "/org/bluez/hci0/dev_67_8A_2D_52_CB_60",
"service_uuid": "00000192-0000-1000-8000-00805f9b34fb",
"char_uuid": "00000777-0000-1000-8000-00805f9b34fb",
"desc_uuid": "00008888-0000-1000-8000-00805f9b34fb",
"reading_interval": 30,
"node": "https://nodes.iota.cafe:443",
"mwm": 14,
"local_pow": false
Expand Down
132 changes: 65 additions & 67 deletions src/ble_connectivity/ble_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ extern crate blurz;
extern crate regex;

use crate::ble_connectivity::handlers::handle_sensor_data;
use crate::device_auth::keystore::KeyManager;
use crate::types::ble_config::BleConfig;
use crate::timestamp_in_sec;
use crate::types::sensor_data::SensorData;
use crate::types::sensor_type::SensorType;
use gateway_core::gateway::publisher::Channel;

use std::sync::{Arc, Mutex};
Expand All @@ -15,86 +16,83 @@ use std::str;
extern crate btleplug;
extern crate rand;

#[cfg(target_os = "linux")]
use blurz::bluetooth_adapter::BluetoothAdapter;
use blurz::bluetooth_device::BluetoothDevice;
use blurz::bluetooth_discovery_session::BluetoothDiscoverySession;
use blurz::bluetooth_gatt_characteristic::BluetoothGATTCharacteristic;
use blurz::bluetooth_gatt_descriptor::BluetoothGATTDescriptor;
use blurz::bluetooth_gatt_service::BluetoothGATTService;
use blurz::bluetooth_session::BluetoothSession;
use regex::Regex;

const UUID_REGEX: &str = r"([0-9a-f]{8})-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}";
lazy_static! {
static ref RE: Regex = Regex::new(UUID_REGEX).unwrap();
}

///
/// Starts the server on the provided port, the server will hand over requests to the handler functions
///
pub async fn start(
device_list: Vec<String>,
ble_config: BleConfig,
channel: Arc<Mutex<Channel>>,
keystore: Arc<Mutex<KeyManager>>,
) -> () {
pub async fn start(device_list: Vec<String>, interval: u64, channel: Arc<Mutex<Channel>>) -> () {
let session = &BluetoothSession::create_session(None).unwrap();
let adapter: BluetoothAdapter = BluetoothAdapter::init(session).unwrap();
let adapter_id = adapter.get_id();
let discover_session = BluetoothDiscoverySession::create_session(&session, adapter_id).unwrap();

discover_session.start_discovery().unwrap();
let devices = adapter.get_device_list().unwrap();
discover_session.stop_discovery().unwrap();

println!("Scanning..");
for device_path in devices {
let device = BluetoothDevice::new(session, device_path.to_string());
println!("{:?}-{:?}", device.get_address(), device.get_name());
}

let device = BluetoothDevice::new(session, ble_config.device_ble_name);

//Main event loop
loop {
if let Err(e) = device.connect(30000) {
println!("Failed to connect, trying again....");
println!("{}", e);
} else {
println!("Connected!");
break;
}
thread::sleep(Duration::from_millis(8000));
}
loop {
let services_list = device.get_gatt_services().unwrap();

for service_path in services_list {
let service = BluetoothGATTService::new(session, service_path.to_string());
let uuid_service = service.get_uuid().unwrap();

if uuid_service == ble_config.service_uuid {
let characteristics = service.get_gatt_characteristics().unwrap();
for characteristic_path in characteristics {
let characteristic =
BluetoothGATTCharacteristic::new(session, characteristic_path);
let uuid_char = characteristic.get_uuid().unwrap();

if uuid_char == ble_config.char_uuid {
let descriptors = characteristic.get_gatt_descriptors().unwrap();
for descriptor_path in descriptors {
let descriptor = BluetoothGATTDescriptor::new(session, descriptor_path);
let uuid_desc = descriptor.get_uuid().unwrap();
let value = descriptor.read_value(None).unwrap();

if uuid_desc == ble_config.desc_uuid {
println!("Value Sent {:?}", str::from_utf8(&value).unwrap());
}
for device in &device_list {
let device_path = format!("/org/bluez/hci0/dev_{}", device.replace(":", "_"));

let device = BluetoothDevice::new(session, device_path);
if let Err(_) = device.connect(30000) {
println!("Failed to connect, trying again in next round....");
continue;
}

let mut data_package = SensorData {
iot2tangle: vec![],
device: device.get_name().unwrap().clone(),
timestamp: serde_json::to_value(timestamp_in_sec()).unwrap(),
};
let services_list = device.get_gatt_services().unwrap();

for service_path in services_list {
let service = BluetoothGATTService::new(session, service_path.to_string());
let uuid_service = service.get_uuid().unwrap();

if uuid_service.starts_with("00055000-0000-0000-") {
let mut characteristics = service.get_gatt_characteristics().unwrap();
characteristics.reverse();

if characteristics.len() < 1usize {
continue;
}

let first_value =
BluetoothGATTCharacteristic::new(session, characteristics[0].clone())
.read_value(None)
.unwrap();

let service_name = str::from_utf8(&first_value).unwrap().replace("\\", "");

let sensor_obj: serde_json::Value =
serde_json::from_str(&service_name).unwrap();
let name = sensor_obj["Name"].as_str().unwrap().to_string();

let mut sensor_type = SensorType {
sensor: name,
data: vec![],
};

for characteristic_path in characteristics.split_off(1) {
let characteristic =
BluetoothGATTCharacteristic::new(session, characteristic_path);
let uuid_char = characteristic.get_uuid().unwrap();

if uuid_char.starts_with("00055000-0000-0000-") {
let value = characteristic.read_value(None).unwrap();
let str_value = str::from_utf8(&value).unwrap();
let data: serde_json::Value = serde_json::from_str(str_value).unwrap();
sensor_type.data.push(data);
}
}
data_package.iot2tangle.push(sensor_type);
}
}

let data_string = serde_json::to_string(&data_package).unwrap();

handle_sensor_data(data_string, &channel);
}
thread::sleep(Duration::from_millis(10000));
thread::sleep(Duration::from_secs(interval));
}
}
52 changes: 11 additions & 41 deletions src/ble_connectivity/handlers.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,23 @@
use crate::device_auth::keystore::{authenticate, calculate_hash, KeyManager};
use crate::timestamp_in_sec;
use crate::types::sensor_data::SensorData;
use std::sync::{Arc, Mutex};

use gateway_core::gateway::publisher::Channel;

///
/// Handles the reuqest from the sensor by parsing the provieded data into the SensorData Format.
/// It authenticates the device through the "device" attribute, and if successfull published the data to the Tangle
/// through the streams channel
///
pub fn handle_sensor_data(
data: String,
channel: &Arc<Mutex<Channel>>,
keystore: &Arc<Mutex<KeyManager>>,
) -> () {
pub fn handle_sensor_data(data: String, channel: &Arc<Mutex<Channel>>) -> () {
let data = data.to_owned();
//let clean_str = std::str::from_utf8(&data).unwrap().replace("\u{0}", "");
let json_data: serde_json::Result<SensorData> = serde_json::from_str(&data);
match json_data {
Ok(mut sensor_data) => {
let hash = keystore
.lock()
.expect("lock keystore")
.keystore
.api_keys_author
.clone();
if authenticate(&sensor_data.device, hash.clone()) {
sensor_data.device.to_string().push_str("_id");
sensor_data.device = calculate_hash(sensor_data.device);
sensor_data.timestamp = serde_json::Value::from(timestamp_in_sec());
println!(
"New Message Recieved -- {:?} -- authorized request by device",
timestamp_in_sec()
);
let mut channel = channel.lock().unwrap();
match channel.write_signed(&sensor_data) {
Ok(msg_id) => println!("{:?}", msg_id),
Err(_e) => {
println!("Error: Could not send data to Tangle, try switching nodes");
()
}
};
} else {
println!(
"New Message Recieved -- {:?} -- unauthorized request blocked",
timestamp_in_sec()
)
}
Ok(sensor_data) => {
println!("New Data Recieved -- {:?}", timestamp_in_sec());
let mut channel = channel.lock().unwrap();
match channel.write_signed(&sensor_data) {
Ok(_) => (),
Err(_e) => {
println!("Error: Could not send data to Tangle, try switching nodes");
()
}
};
}
Err(_e) => {
println!(
Expand Down
1 change: 0 additions & 1 deletion src/device_auth/keystore.json

This file was deleted.

Loading

0 comments on commit 9294690

Please sign in to comment.