Skip to content

Commit

Permalink
More work, but keeps disconnecting
Browse files Browse the repository at this point in the history
  • Loading branch information
evoggy committed Aug 23, 2024
1 parent 64a73f1 commit 70d04fa
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 86 deletions.
184 changes: 109 additions & 75 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
use std::path::Path;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use std::{thread, time};
use tokio::runtime::Runtime;

use crazyflie_lib::Crazyflie;
use futures::StreamExt;
use tauri::Manager;
use tokio::sync::mpsc;

//use tokio::sync::mpsc;
use flume as mpsc;
use futures_util::task::SpawnExt;
use ts_rs::TS;

#[tauri::command]
Expand All @@ -31,7 +33,7 @@ async fn connect(uri: &str, state: tauri::State<'_, BackendState>) -> Result<(),
state
.cmd
.send(CrazyflieBackendCommand::Connect(uri.to_string()))
.await

.map_err(|e| format!("{:?}", e))?;
Ok(())
}
Expand All @@ -41,7 +43,7 @@ async fn disconnect(state: tauri::State<'_, BackendState>) -> Result<(), String>
state
.cmd
.send(CrazyflieBackendCommand::Disconnect)
.await

.map_err(|e| format!("{:?}", e))?;
Ok(())
}
Expand All @@ -52,7 +54,7 @@ async fn start_scan(address: &str, state: tauri::State<'_, BackendState>) -> Res
state
.cmd
.send(CrazyflieBackendCommand::StartScan(address.to_string()))
.await

.map_err(|e| format!("{:?}", e))?;
Ok(())
}
Expand All @@ -63,7 +65,7 @@ async fn stop_scan(state: tauri::State<'_, BackendState>) -> Result<(), String>
state
.cmd
.send(CrazyflieBackendCommand::StopScan)
.await

.map_err(|e| format!("{:?}", e))?;
Ok(())
}
Expand Down Expand Up @@ -94,20 +96,26 @@ enum CrazyflieBackendState {
}

#[derive(Debug, serde::Serialize, TS)]
#[ts(export, export_to = "../src/backend-interface.ts")]
#[ts(export, export_to = "../src/interface/scan_response.ts")]
struct ScanResponse {
uris: Vec<String>,
err: Option<String>,
}

#[derive(Debug, serde::Serialize, TS)]
#[ts(export, export_to = "../src/backend-interface.ts")]
#[ts(export, export_to = "../src/interface/connected_event.ts")]
struct ConnectedEvent {
connected: bool,
uri: String,
err: Option<String>,
}

#[derive(Debug, serde::Serialize, TS)]
#[ts(export, export_to = "../src/interface/console_event.ts")]
struct ConsoleEvent {
message: String,
}

async fn crazyflie_backend_scan(
mut ui_to_cf_rx: mpsc::Receiver<CrazyflieBackendCommand>,
address: String,
Expand All @@ -117,33 +125,34 @@ async fn crazyflie_backend_scan(
//let mut ui_to_cf_rx_inner = ui_to_cf_rx.unwrap();
loop {
println!("Looping around to scan again!");
tokio::select! {
found = link_context.scan([0xE7; 5]) => {
println!("Scanning for Crazyflies on address {}", address);
match found {
Ok(uris) => {
let response = ScanResponse { uris, err: None };
t.emit_all("scan", &response).unwrap();
}
Err(e) => {
println!("Error scanning for Crazyflies: {:?}", e);
let response = ScanResponse { uris: vec![], err: Some(e.to_string()) };
t.emit_all("scan", &response).unwrap();
break;
}
}
println!("Scanning for Crazyflies on address {}", address);
match link_context.scan([0xE7; 5]).await {
Ok(uris) => {
let response = ScanResponse { uris, err: None };
t.emit_all("scan", &response).unwrap();
}
Some(input) = ui_to_cf_rx.recv() => {
match input {
CrazyflieBackendCommand::StopScan => {
break;
}
_ => {
println!("Error: Received CF command: {:?} in scan state!", input);
}
}
Err(e) => {
println!("Error scanning for Crazyflies: {:?}", e);
let response = ScanResponse { uris: vec![], err: Some(e.to_string()) };
t.emit_all("scan", &response).unwrap();
break;
}
}

match ui_to_cf_rx.try_recv() {
Ok(input) => {
match input {
CrazyflieBackendCommand::StopScan => {
println!("Will be exiting scan mode!");
break;
}
_ => {
println!("Error: Received CF command: {:?} in scan state!", input);
}
}
}
_ => {}
}
}
println!("Exiting scan mode!");

Expand All @@ -157,44 +166,69 @@ async fn crazyflie_backend_connected(
) -> mpsc::Receiver<CrazyflieBackendCommand> {
let link_context = crazyflie_link::LinkContext::new(async_executors::AsyncStd);

let cf = crazyflie_lib::Crazyflie::connect_from_uri(
async_executors::AsyncStd,
&link_context,
uri.as_str(),
)
.await.unwrap();

// match cf {
// Ok(cf) => {
// println!("Connected to Crazyflie on {}", uri);
// let response = ConnectedEvent {
// connected: true,
// uri,
// err: None,
// };
// t.emit_all("connected", &response).unwrap();

// let mut console_stream = cf.console.line_stream().await;
println!("Calling connect now on {}!", uri);

let cf = async_executors::AsyncStd::block_on(async {
crazyflie_lib::Crazyflie::connect_from_uri(async_executors::AsyncStd, &link_context, uri.as_str())
.await
});

match cf {
Ok(cf) => {
println!("Connected to Crazyflie on {}", uri);
let response = ConnectedEvent {
connected: true,
uri,
err: None,
};
t.emit_all("connected", &response).unwrap();

let (tx, rx) = flume::unbounded::<String>();

std::thread::spawn( move || {
while let Ok(line) = rx.recv() {
let response = ConsoleEvent { message: line.clone()};
t.emit_all("console", &response).unwrap();
println!("Received: {}", line);
}
});

println!("Starting console");

//async_executors::AsyncStd::block_on(async {
let mut stream = cf.console.line_stream().await;

async_executors::AsyncStd.spawn(async move {
while let Some(line) = stream.next().await {
tx.send_async(line).await.expect("Failed to send line");
}
println!("Exiting console stream loop");
}).unwrap();

//}).unwrap();

println!("Starting to sleep a bit");

async_std::task::sleep(Duration::from_secs(10)).await;

println!("Have Slept, waiting for disconnect");

cf.wait_disconnect().await;

println!("Exiting main connected loop");


// }
// Err(e) => {
// println!("Error connecting to Crazyflie on {}: {:?}", uri, e);
// let response = ConnectedEvent {
// connected: false,
// uri,
// err: Some(e.to_string()),
// };
// t.emit_all("connected", &response).unwrap();
// }
// }

//let mut console_stream = cf.console.line_stream().await;

// tokio::select! {
// Some(line) = console_stream.next() => {
// println!("Console line: {:?}", line);
// }
// }
}
Err(e) => {
println!("Error connecting to Crazyflie on {}: {:?}", uri, e);
let response = ConnectedEvent {
connected: false,
uri,
err: Some(e.to_string()),
};
t.emit_all("connected", &response).unwrap();
}
}

ui_to_cf_rx
}
Expand All @@ -212,26 +246,26 @@ async fn crazyflie_backend(
// Connected -> Idle
// if state

let cmd = ui_to_cf_rx.recv().await;
let cmd = ui_to_cf_rx.recv();

match cmd {
Some(output) => match output {
Ok(output) => match output {
CrazyflieBackendCommand::StartScan(address) => {
println!("Start scanning for Crazyflies on address {}", address);
ui_to_cf_rx =
crazyflie_backend_scan(ui_to_cf_rx, address.to_string(), t.clone()).await;
}
CrazyflieBackendCommand::Connect(uri) => {
println!("Con to Crazyflie on {}", uri);
println!("Connect to Crazyflie on {}", uri);
ui_to_cf_rx =
crazyflie_backend_connected(ui_to_cf_rx, uri.to_string(), t.clone()).await;
}
_ => {
println!("Error: Received CF command: {:?} in main state!", output);
}
},
None => {
println!("Error: Received None from ui_to_cf_rx in main state!");
Err(e) => {
println!("Error receiving CF command: {:?}", e);
}
}
// tokio::select! {
Expand All @@ -246,7 +280,7 @@ async fn crazyflie_backend(
}

fn main() {
let (ui_to_cf_tx, ui_to_cf_rx) = mpsc::channel::<CrazyflieBackendCommand>(1);
let (ui_to_cf_tx, ui_to_cf_rx) = mpsc::unbounded();

tauri::Builder::default()
.manage(BackendState::new(ui_to_cf_tx))
Expand Down
13 changes: 4 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { Sidebar, Menu, MenuItem, SubMenu } from 'react-pro-sidebar';
import 'bootstrap/dist/css/bootstrap.min.css';

import ConnectionModal from "./components/connection_modal";
import ConsoleTab from "./components/console_tab";
import BackEnd from './backend';

function App() {
const [greetMsg, setGreetMsg] = useState("");

Check failure on line 25 in src/App.tsx

View workflow job for this annotation

GitHub Actions / test-tauri (macos-latest)

'greetMsg' is declared but its value is never read.

Check failure on line 25 in src/App.tsx

View workflow job for this annotation

GitHub Actions / test-tauri (ubuntu-20.04)

'greetMsg' is declared but its value is never read.

Check failure on line 25 in src/App.tsx

View workflow job for this annotation

GitHub Actions / test-tauri (windows-latest)

'greetMsg' is declared but its value is never read.
Expand All @@ -40,14 +42,15 @@ function App() {
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="fly" element={<Fly />} />
<Route path="console" element={<Console />} />
<Route path="console" element={<ConsoleTab />} />

{/* Using path="*"" means "match anything", so this route
acts like a catch-all for URLs that we don't have explicit
routes for. */}
<Route path="*" element={<NoMatch />} />
</Route>
</Routes>
<BackEnd/>
</div>
);
}
Expand Down Expand Up @@ -132,14 +135,6 @@ function Fly() {
);
}

function Console() {
return (
<div>
<pre>Console output right here</pre>
</div>
);
}

function NoMatch() {
return (
<div>
Expand Down
47 changes: 47 additions & 0 deletions src/backend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useContext } from 'react';
import { listen } from "@tauri-apps/api/event";
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import Table from 'react-bootstrap/Table';

import { toast } from 'react-toastify';

import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';

import { store } from './store.js';

import { ConsoleEvent } from './interface/console_event';

interface ConsoleEventMessage {
payload: ConsoleEvent;
}

function BackEnd() {
const { state, dispatch } = useContext(store);

const changeColor = () => {
dispatch({ type: "CHANGE_COLOR", payload: "blue" });
};

useEffect(() => {
console.log("Backend loaded");
const unListen = listen("console", (e: ConsoleEventMessage) => {
//setConsoleText(consoleText + e.payload.message + "\n");
console.log("Got console stuff off backend")
dispatch({ type: "CONSOLE", payload: e.payload.message });

});

return () => {
console.log("Backend unloaded");
unListen.then((f) => f());
};
}, []);


return null;
}

export default BackEnd;
2 changes: 1 addition & 1 deletion src/components/connection_modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'bootstrap/dist/css/bootstrap.min.css';

import { invoke } from "@tauri-apps/api/tauri";

import { ScanResponse } from '../backend-interface';
import { ScanResponse } from '../interface/scan_response';


// interface ProgressEventPayload {
Expand Down
Loading

0 comments on commit 70d04fa

Please sign in to comment.