Skip to content

Instantly share code, notes, and snippets.

@categulario
Created July 14, 2017 01:54
Show Gist options
  • Save categulario/ac5c8677bc692b5439ece543853ad9e0 to your computer and use it in GitHub Desktop.
Save categulario/ac5c8677bc692b5439ece543853ad9e0 to your computer and use it in GitHub Desktop.
parse from NMEA stream
use std::io;
use std::str;
use bytes::BytesMut;
use tokio_io::codec::{Encoder, Decoder};
use std::str::FromStr;
fn extract_coord(num: f32, orientation: &str) -> f32 {
let res = num%100.0;
let ans = (num/100.0).floor() + res/60.0;
if orientation == "N" || orientation == "E" {
return ans;
} else {
return -ans;
}
}
pub struct Pos {
lat: f32,
lon: f32,
device: i16,
}
impl FromStr for Pos {
type Err = String;
fn from_str(s: &str) -> Result<Pos, Self::Err> {
let pieces:Vec<&str> = s.split(',').collect();
match pieces.get(0) {
Some(piece) => if *piece == "\n$POS" {
Ok(Pos{
lon : extract_coord(pieces.get(6).unwrap().parse().unwrap(), pieces.get(7).unwrap()),
lat : extract_coord(pieces.get(4).unwrap().parse().unwrap(), pieces.get(5).unwrap()),
device : pieces.get(1).unwrap().parse().unwrap(),
})
} else {
Err("No es una posición".to_string())
},
None => Err("Falló la conversión".to_string()),
}
}
}
pub struct LineCodec;
impl Decoder for LineCodec {
type Item = String;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
match buf.iter().position(|&b| b == b'#') {
Some(i) => {
let line = buf.split_to(i);
// remove the #
buf.split_to(1);
match str::from_utf8(&line) {
Ok(s) => {
let string = s.to_string();
println!("{:?}", string);
Ok(Some(string))
},
Err(_) => Ok(None),
}
},
None => Ok(None),
}
}
}
impl Encoder for LineCodec {
type Item = String;
type Error = io::Error;
fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
buf.extend(msg.as_bytes());
Ok(())
}
}
#[test]
fn test_parse_coords() {
assert_eq!(extract_coord(2036.3883, "N"), 20.606472);
assert_eq!(extract_coord(10323.9808, "W"), -103.39967);
assert_eq!(extract_coord(2036.3883, "S"), -20.606472);
assert_eq!(extract_coord(10323.9808, "E"), 103.39967);
}
#[test]
fn test_parse_multibyte_to_pos() {
let pos:Pos = "\n$POS,1289,105127.000,A,2036.3883,N,10323.9808,W,0.0,1.7,130717,,,A/0000,0/0/93069700//f97/".parse().unwrap();
assert_eq!(pos.lat, 20.6064716666666666);
assert_eq!(pos.lon, -103.39967);
assert_eq!(pos.device, 1289);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment