Skip to content

Commit

Permalink
fix: bug when reading gps coordinates in the southern and eastern hem…
Browse files Browse the repository at this point in the history
…ispheres

Fixed bug when reading gps coordinates in the southern and eastern hemispheres
  • Loading branch information
DamianoPellegrini authored Jan 13, 2024
2 parents 246e288 + 69c5443 commit 8e16afb
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 19 deletions.
29 changes: 14 additions & 15 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use nom::{
combinator::{cond, verify},
error::ParseError,
multi::{length_count, length_data},
number::streaming::{be_u16, be_u32, be_u64, be_u8},
number::streaming::{be_i32, be_u16, be_u32, be_u64, be_u8},
IResult, Parser,
};

Expand Down Expand Up @@ -138,8 +138,8 @@ fn record<'a>(codec: Codec) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], AVLReco
let (input, timestamp) = be_u64(input)?;
let (input, priority) = priority(input)?;

let (input, longitude) = be_u32(input)?;
let (input, latitude) = be_u32(input)?;
let (input, longitude) = be_i32(input)?;
let (input, latitude) = be_i32(input)?;
let (input, altitude) = be_u16(input)?;
let (input, angle) = be_u16(input)?;
let (input, satellites) = be_u8(input)?;
Expand All @@ -156,18 +156,8 @@ fn record<'a>(codec: Codec) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], AVLReco
// contruct a datetime using the timestamp in since the unix epoch
let timestamp = Utc.timestamp_millis_opt(timestamp as i64).single().unwrap();

let longitude = if longitude & 0x80000000 != 0 {
-(longitude as i32)
} else {
longitude as i32
} as f64
/ 10000000.0;
let latitude = if latitude & 0x80000000 != 0 {
-(latitude as i32)
} else {
latitude as i32
} as f64
/ 10000000.0;
let longitude = longitude as f64 / 10000000.0;
let latitude = latitude as f64 / 10000000.0;

Ok((
input,
Expand Down Expand Up @@ -673,4 +663,13 @@ mod tests {
panic!("Expected Incomplete error");
}
}

#[test]
fn parse_negative_emisphere_coordinates() {
let input = hex::decode("00000000000000460801000001776D58189001FA0A1F00F1194D80009C009D05000F9B0D06EF01F0001505C80045019B0105B5000BB6000A424257430F8044000002F1000060191000000BE1000100006E2B").unwrap();
let (input, frame) = tcp_frame(&input).unwrap();
assert_eq!(input, &[]);
assert_eq!(frame.records[0].longitude, -10.0);
assert_eq!(frame.records[0].latitude, -25.0);
}
}
8 changes: 4 additions & 4 deletions src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<S: Read + Write> TeltonikaStream<S> {
///
/// If this function encounters any form of I/O or other error, an error variant will be returned as in [`Read::read`].
///
/// If no bytes are read from the stream, an error king of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If no bytes are read from the stream, an error kind of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If the IMEI cannot be parsed, an error kind of [`std::io::ErrorKind::InvalidData`] is returned.
pub fn read_imei(&mut self) -> io::Result<String> {
let mut parse_buf: Vec<u8> = Vec::with_capacity(self.imei_buf_capacity * 2);
Expand Down Expand Up @@ -94,7 +94,7 @@ impl<S: Read + Write> TeltonikaStream<S> {
///
/// If this function encounters any form of I/O or other error, an error variant will be returned as in [`Read::read`].
///
/// If no bytes are read from the stream, an error king of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If no bytes are read from the stream, an error kind of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If the frame cannot be parsed, an error kind of [`std::io::ErrorKind::InvalidData`] is returned.
pub fn read_frame(&mut self) -> io::Result<AVLFrame> {
let mut parse_buf: Vec<u8> = Vec::with_capacity(self.packet_buf_capacity * 2);
Expand Down Expand Up @@ -220,7 +220,7 @@ impl<S: AsyncReadExt + AsyncWriteExt + Unpin> TeltonikaStream<S> {
///
/// If this function encounters any form of I/O or other error, an error variant will be returned as in [`Read::read`].
///
/// If no bytes are read from the stream, an error king of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If no bytes are read from the stream, an error kind of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If the IMEI cannot be parsed, an error kind of [`std::io::ErrorKind::InvalidData`] is returned.
pub async fn read_imei_async(&mut self) -> io::Result<String> {
let mut parse_buf: Vec<u8> = Vec::with_capacity(self.imei_buf_capacity * 2);
Expand Down Expand Up @@ -261,7 +261,7 @@ impl<S: AsyncReadExt + AsyncWriteExt + Unpin> TeltonikaStream<S> {
///
/// If this function encounters any form of I/O or other error, an error variant will be returned as in [`Read::read`].
///
/// If no bytes are read from the stream, an error king of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If no bytes are read from the stream, an error kind of [`std::io::ErrorKind::ConnectionReset`] is returned.
/// If the frame cannot be parsed, an error kind of [`std::io::ErrorKind::InvalidData`] is returned.
pub async fn read_frame_async(&mut self) -> io::Result<AVLFrame> {
let mut parse_buf: Vec<u8> = Vec::with_capacity(self.packet_buf_capacity * 2);
Expand Down

0 comments on commit 8e16afb

Please sign in to comment.