initial kiss

This commit is contained in:
John Goerzen 2019-10-30 21:39:13 -05:00
parent a5a9978281
commit 65b5dbed64
3 changed files with 38 additions and 29 deletions

View File

@ -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()?;
}
}

View File

@ -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();

View File

@ -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");