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