Skip to content

Commit

Permalink
Merge pull request #2 from SaturnHafen/clients
Browse files Browse the repository at this point in the history
Clients
  • Loading branch information
SaturnHafen authored Feb 1, 2022
2 parents 83bb0e2 + 20c8859 commit 65091c0
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 205 deletions.
2 changes: 1 addition & 1 deletion ev3-tunnel-entry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tungstenite = "0.16.0"
websocket = "0.26.2"
serde_json = "1"
confy = "0.4.0"
serde = { version = "1.0", features = ["derive"] }
190 changes: 89 additions & 101 deletions ev3-tunnel-entry/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use serde::{Deserialize, Serialize};
use serde_json::{from_str, Value};
use std::io::prelude::*;
use std::net::TcpStream;
use tungstenite::client::connect;
use tungstenite::protocol::{Message, WebSocket};
use tungstenite::stream::MaybeTlsStream;
use websocket::sync::stream::TlsStream;
use websocket::sync::Client;
use websocket::{ClientBuilder, Message, OwnedMessage};

mod labview;

Expand Down Expand Up @@ -36,22 +36,17 @@ fn load_config() -> Config {
config
}

fn connect_ws(mut config: Config) -> WebSocket<MaybeTlsStream<TcpStream>> {
fn connect_ws(mut config: Config) -> Client<TlsStream<TcpStream>> {
println!(
"Connecting to {}:{}/{}",
config.remote, config.port, config.path
);
let (mut connection, _response) = connect(format![
"ws://{}:{}/{}",
config.remote, config.port, config.path
])
.expect(
format![
"Couldn't connect to remote <{}> on port <{}>",
config.remote, config.port
]
.as_str(),
);
let mut client = ClientBuilder::new(
format!["wss://{}:{}/{}", config.remote, config.port, config.path].as_str(),
)
.unwrap()
.connect_secure(None)
.unwrap();

let message: String;

Expand All @@ -61,71 +56,75 @@ fn connect_ws(mut config: Config) -> WebSocket<MaybeTlsStream<TcpStream>> {
}

println!("Sending: {}", message);
connection
.write_message(Message::Text(message)) // JSON as specifiied in ev3cconnect README

client
.send_message(&Message::text(message)) // JSON as specifiied in ev3cconnect README
.expect("Couldn't queue init message");

let response: Message = connection
.read_message()
let response = client
.recv_message()
.expect("Couldn't read from Websocket...");

if response.is_text() {
println!("Got: {:?}", response.to_text().unwrap());
match response {
OwnedMessage::Text(payload) => {
println!("Got: {:?}", payload);

let resp: Value = from_str(response.to_text().expect("Couldn't read text..."))
.expect("Couldn't parse json...");
let resp: Value = from_str(&payload).expect("Couldn't parse json...");

if resp["Rejected"] != Value::Null {
let error = resp["Rejected"].to_string();
if resp["Control"] != Value::Null {
let ev3 = resp["Control"].to_string();
config.ev3 = Some(ev3);

println!(
"Couldn't connect to remote, please inform the server operator. Reason: {}",
error
);
panic!();
}
store_path(CONFIG_PATH, &config).expect("Couldn't store config...");
}

if resp["Control"] != Value::Null {
let ev3 = resp["Control"].to_string();
config.ev3 = Some(ev3);
if resp["Rejected"] != Value::Null {
let error = resp["Rejected"].to_string();

store_path(CONFIG_PATH, &config).expect("Couldn't store config...");
}
// store to Config

if resp["Queue"] != Value::Null {
println!(
"--------------------------------------------------------------------------------"
);
println!(
"Awaiting control from ev3. Until then, the ev3 will NOT show up in LEGO LabView!"
);
println!(
"--------------------------------------------------------------------------------"
);
println!(
"Couldn't connect to remote, please inform the server operator. Reason: {}",
error
);
panic!();
}

loop {
let response: Message = connection
.read_message()
.expect("Couldn't read from Websocket...");
if resp["Queue"] != Value::Null {
println!(
"--------------------------------------------------------------------------------"
);
println!(
"Awaiting control from ev3. Until then, the ev3 will NOT show up in LEGO LabView!"
);
println!(
"--------------------------------------------------------------------------------"
);

if response.is_text() {
let resp: Value = from_str(response.to_text().expect("Couldn't read text..."))
.expect("Couldn't parse json...");
loop {
let response = client
.recv_message()
.expect("Couldn't read from Websocket...");

if resp["Control"] != Value::Null {
let ev3 = resp["Control"].to_string();
config.ev3 = Some(ev3);
match response {
OwnedMessage::Text(payload) => {
let resp: Value = from_str(&payload).expect("Couldn't parse json...");

store_path(CONFIG_PATH, &config).expect("Couldn't store config...");
break;
if resp["Control"] != Value::Null {
let ev3 = resp["Control"].to_string();
config.ev3 = Some(ev3);

store_path(CONFIG_PATH, &config).expect("Couldn't store config...");
break;
}
}
_ => {}
}
}
}
}
_ => (),
}

connection
client
}

fn main() {
Expand All @@ -134,64 +133,53 @@ fn main() {
let mut labview_connection = labview::connect();

let mut buf = [0; 65555]; // 65536 is max value of u16, just use a few more for good measure more for length
let mut length;
let mut response;

loop {
let result = labview_connection.read(&mut buf);

match result {
Ok(x) => length = x,
Err(x) => {
println!(
"Connection to LabView was closed, attempting to reconnect... (Error: {:?})",
x
);
labview_connection = labview::connect();
continue;
}
}
let len = labview_connection
.read(&mut buf)
.expect("Couldn't read from LabView connection");

websocket
.write_message(Message::Binary((&buf[..length]).to_vec()))
.send_message(&Message::binary(&buf[..len]))
.expect("Couldn't write to WebSocket connection...");

if buf[4].eq(&0x00) || buf[4].eq(&0x01) {
// DIRECT_COMMAND_REPLY || SYSTEM_COMMAND_REPLY
loop {
response = websocket
.read_message()
.recv_message()
.expect("Couldn't read from websocket connection...");

if response.is_binary() {
break;
} else if response.is_ping() {
websocket
.write_message(Message::Pong(response.into_data()))
.expect("Couldn't send pong reply");
} else {
println!("No binary frame, got: {}", response);
}
}
let data = response.into_data();
match response {
OwnedMessage::Ping(payload) => {
websocket
.send_message(&Message::pong(payload))
.expect("Couldn't send pong reply");
}

//println!(" | len | cnt |rs| pl ");
//println!("Recv: 0x|{}|", to_hex_string(&data));
OwnedMessage::Binary(payload) => {
if (payload.len() - 2) as u16
!= (((payload[1] as u16) << 8) | payload[0] as u16)
{
panic!(
"Expected size does not match received size! (Expected: {}, Received: {})",
(((payload[0] as u16) << 8) | payload[1] as u16),
payload.len() - 2
);
}

labview_connection
.write(&payload)
.expect("Couldn't write to LabView connection...");

if (data.len() - 2) as u16 != (((data[1] as u16) << 8) | data[0] as u16) {
panic!(
"Expected size does not match received size! (Expected: {}, Received: {})",
(((data[0] as u16) << 8) | data[1] as u16),
data.len() - 2
);
break;
}
_ => {}
}
}

labview_connection
.write(&data)
.expect("Couldn't write to LabView connection...");
} else if buf[4].eq(&0x80) || buf[4].eq(&0x81) {
// DIRECT_COMMAND_NO_REPLY || SYSTEM_COMMAND_NO_REPLY

continue;
} else {
debug_assert!(false, "Got a strange message type!");
Expand Down
4 changes: 2 additions & 2 deletions ev3-tunnel-exit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tungstenite = "0.16.0"
regex = "1"
websocket = "0.26.2"
io_bluetooth = "0.1"
confy = "0.4.0"
serde = { version = "1.0", features = ["derive"] }
76 changes: 13 additions & 63 deletions ev3-tunnel-exit/src/ev3.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use regex::Regex;
use std::io::prelude::*;
use std::net::{SocketAddr, TcpStream, UdpSocket};
use std::str::from_utf8;
use io_bluetooth::bt::{self, BtAddr, BtStream};
use std::iter;

pub fn to_hex_string(bytes: &[u8]) -> String {
let strs: Vec<String> = bytes.iter().map(|b| format!("{:02X}", b)).collect();
Expand All @@ -10,79 +8,31 @@ pub fn to_hex_string(bytes: &[u8]) -> String {
}

pub struct EV3 {
connection: TcpStream,
connection: BtStream,
pub name: String,
}

impl EV3 {
pub fn connect() -> EV3 {
let socket = UdpSocket::bind(SocketAddr::from(([0, 0, 0, 0], 3015)))
.expect("couldn't bind to address");
pub fn connect(ev3: BtAddr, name: &String) -> EV3 {
println!("Connecting to {}", ev3);

let mut buf = [0; 70];
let socket = BtStream::connect(iter::once(&ev3), bt::BtProtocol::RFCOMM).unwrap();

println!("Receiving data from ev3...");
let (mut recv_count, remote) = socket.recv_from(&mut buf).expect("Didn't receive data");

let mut recv_data = &mut buf[..recv_count];

let re =
Regex::new(r"Serial-Number: (\w*)\s\nPort: (\d{1,5})\s\nName: (.*)\s\nProtocol: EV3")
.unwrap();

let re_match = re
.captures(from_utf8(&recv_data).expect("Invalid utf-8 sequence"))
.unwrap();

println!("Replying to enable TCP...");
let send_count = socket
.send_to(&[0; 10], remote)
.expect("Couldn't send data");

if send_count != 10 {
panic!(
"Should be able to send packet with size 10, was able to send {}!",
send_count
);
match socket.peer_addr() {
Ok(addr) => println!("Successfully connected to {}.", addr.to_string()),
Err(err) => panic!("An error occured while connecting: {:?}", err),
}

let mut stream = TcpStream::connect(SocketAddr::from((remote.ip(), 5555)))
.expect("TCP-Connection failed");

let unlock_payload = format!(
"GET /target?sn={} VMTP1.0\nProtocol: EV3",
re_match.get(1).unwrap().as_str()
);

let name = re_match.get(3).unwrap().as_str().to_string();

stream
.write(unlock_payload.as_bytes())
.expect("Couldn't send data to connection");

recv_count = stream
.read(&mut buf)
.expect("Couldn't read data from connection");

recv_data = &mut buf[..recv_count];

print!(
"Brick reply: {}",
from_utf8(&recv_data).expect("Invalid utf-8 sequence")
);

println!("Brick should be unlocked!");

EV3 {
connection: stream,
name,
connection: socket,
name: name.to_string(),
}
}

pub fn send_command(&mut self, payload: &[u8]) -> Vec<u8> {
let _send_count = self
.connection
.write(&payload)
.send(&payload)
.expect("Couldn't write to EV3 connection...");

println!("Send to EV3:");
Expand All @@ -97,7 +47,7 @@ impl EV3 {
} else {
let recv_count = self
.connection
.read(&mut recv_buf)
.recv(&mut recv_buf)
.expect("Couldn't read from connection");

let recv_data = &recv_buf[..recv_count];
Expand Down
Loading

0 comments on commit 65091c0

Please sign in to comment.