mirror of https://github.com/jgoerzen/xbnet.git
initial kiss
This commit is contained in:
parent
a5a9978281
commit
65b5dbed64
42
src/kiss.rs
42
src/kiss.rs
|
@ -16,43 +16,43 @@
|
|||
*/
|
||||
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use crate::lorastik::{LoraStik, ReceivedFrames};
|
||||
use crossbeam_channel;
|
||||
use std::io::{BufRead};
|
||||
use crate::lorastik::{LoraStik};
|
||||
pub use crate::pipe::loratostdout;
|
||||
|
||||
// Spec: http://www.ax25.net/kiss.aspx
|
||||
|
||||
const MAXFRAME: usize = 200;
|
||||
const FEND: u8 = 0xC0;
|
||||
const FESC: u8 = 0xDB;
|
||||
const TFEND: u8 = 0xDC;
|
||||
const TFESC: u8 = 0xDD;
|
||||
// const FESC: u8 = 0xDB;
|
||||
// const TFEND: u8 = 0xDC;
|
||||
// const TFESC: u8 = 0xDD;
|
||||
|
||||
/// A thread for stdin processing
|
||||
pub fn stdintolora(ls: &mut LoraStik) -> io::Result<()> {
|
||||
pub fn stdintolorakiss(ls: &mut LoraStik, maxframesize: usize) -> io::Result<()> {
|
||||
let stdin = io::stdin();
|
||||
let mut br = io::BufReader::new(stdin);
|
||||
|
||||
let mut buf = vec![0u8; 8192];
|
||||
|
||||
loop {
|
||||
let res = br.read(&mut buf)?;
|
||||
let res = br.read_until(FEND, &mut buf)?;
|
||||
if res == 0 {
|
||||
// EOF
|
||||
return Ok(());
|
||||
} else if res < 2 {
|
||||
// Every frame from stdin will start with FEND and a control character;
|
||||
// we got just FEND, we are in the space between to frames, so we should just
|
||||
// proceed. Similar if we have some non-data frame.
|
||||
continue;
|
||||
} else if buf[0] != 0 {
|
||||
// A TNC control frame; do not send.
|
||||
continue;
|
||||
}
|
||||
|
||||
for chunk in buf[0..res].chunks(MAXFRAME) {
|
||||
// OK, we've got it, now make sure it doesn't exceed the limit and transmit.
|
||||
for chunk in buf[0..res].chunks(maxframesize) {
|
||||
ls.transmit(&chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn loratostdout(receiver: crossbeam_channel::Receiver<ReceivedFrames>) -> io::Result<()> {
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
loop {
|
||||
let data = receiver.recv().unwrap();
|
||||
stdout.write_all(&data.0)?;
|
||||
stdout.flush()?;
|
||||
}
|
||||
}
|
||||
|
||||
// loratostdout just comes from pipe
|
||||
|
|
|
@ -25,7 +25,7 @@ use crossbeam_channel;
|
|||
use hex;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
// use format_escape_default::format_escape_default;
|
||||
use format_escape_default::format_escape_default;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn mkerror(msg: &str) -> Error {
|
||||
|
@ -202,7 +202,7 @@ impl LoraStik {
|
|||
fn handlerx(&mut self, msg: String, readqual: bool) -> io::Result<()> {
|
||||
if msg.starts_with("radio_rx ") {
|
||||
if let Ok(mut decoded) = hex::decode(&msg.as_bytes()[10..]) {
|
||||
// trace!("DECODED: {}", format_escape_default(&decoded));
|
||||
trace!("DECODED: {}", format_escape_default(&decoded));
|
||||
let radioqual = if readqual {
|
||||
self.ser.writeln(String::from("radio get snr"))?;
|
||||
let snr = self.readerlinesrx.recv().unwrap();
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -25,6 +25,7 @@ mod ser;
|
|||
mod lorastik;
|
||||
mod pipe;
|
||||
mod ping;
|
||||
mod kiss;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
@ -45,6 +46,10 @@ struct Opt {
|
|||
#[structopt(long, parse(from_os_str))]
|
||||
initfile: Option<PathBuf>,
|
||||
|
||||
/// Maximum frame size sent to radio [10..250] (valid only for ping and kiss)
|
||||
#[structopt(long, default_value = "100")]
|
||||
maxpacketsize: usize,
|
||||
|
||||
/// Amount of time (ms) to pause before transmitting a packet
|
||||
/* The
|
||||
main purpose of this is to give the othe rradio a chance to finish
|
||||
|
@ -75,15 +80,13 @@ struct Opt {
|
|||
#[derive(Debug, StructOpt)]
|
||||
enum Command {
|
||||
/// Pipe data across raios
|
||||
Pipe {
|
||||
/// Maximum frame size sent to radio [10..250]
|
||||
#[structopt(long, default_value = "100")]
|
||||
maxpacketsize: usize,
|
||||
},
|
||||
Pipe,
|
||||
/// Transmit ping requests
|
||||
Ping,
|
||||
/// Receive ping requests and transmit pongs
|
||||
Pong,
|
||||
/// Pipe KISS data across the radios
|
||||
Kiss,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -101,11 +104,17 @@ fn main() {
|
|||
let mut ls2 = ls.clone();
|
||||
thread::spawn(move || ls2.readerthread().expect("Failure in readerthread"));
|
||||
|
||||
let maxpacketsize = opt.maxpacketsize;
|
||||
|
||||
match opt.cmd {
|
||||
Command::Pipe{ maxpacketsize } => {
|
||||
Command::Pipe => {
|
||||
thread::spawn(move || pipe::stdintolora(&mut ls, maxpacketsize).expect("Failure in stdintolora"));
|
||||
pipe::loratostdout(radioreceiver).expect("Failure in loratostdout");
|
||||
},
|
||||
Command::Kiss => {
|
||||
thread::spawn(move || kiss::stdintolorakiss(&mut ls, maxpacketsize).expect("Failure in stdintolorakiss"));
|
||||
kiss::loratostdout(radioreceiver).expect("Failure in loratostdout");
|
||||
},
|
||||
Command::Ping => {
|
||||
thread::spawn(move || ping::genpings(&mut ls).expect("Failure in genpings"));
|
||||
pipe::loratostdout(radioreceiver).expect("Failure in loratostdout");
|
||||
|
|
Loading…
Reference in New Issue