use crate::{
byte_converter::*, converting_callback_receiver::ConvertingCallbackReceiver, converting_receiver::ConvertingReceiver, device::*,
ip_connection::GetRequestSender,
};
pub enum GpsBrickletFunction {
GetCoordinates,
GetStatus,
GetAltitude,
GetMotion,
GetDateTime,
Restart,
SetCoordinatesCallbackPeriod,
GetCoordinatesCallbackPeriod,
SetStatusCallbackPeriod,
GetStatusCallbackPeriod,
SetAltitudeCallbackPeriod,
GetAltitudeCallbackPeriod,
SetMotionCallbackPeriod,
GetMotionCallbackPeriod,
SetDateTimeCallbackPeriod,
GetDateTimeCallbackPeriod,
GetIdentity,
CallbackCoordinates,
CallbackStatus,
CallbackAltitude,
CallbackMotion,
CallbackDateTime,
}
impl From<GpsBrickletFunction> for u8 {
fn from(fun: GpsBrickletFunction) -> Self {
match fun {
GpsBrickletFunction::GetCoordinates => 1,
GpsBrickletFunction::GetStatus => 2,
GpsBrickletFunction::GetAltitude => 3,
GpsBrickletFunction::GetMotion => 4,
GpsBrickletFunction::GetDateTime => 5,
GpsBrickletFunction::Restart => 6,
GpsBrickletFunction::SetCoordinatesCallbackPeriod => 7,
GpsBrickletFunction::GetCoordinatesCallbackPeriod => 8,
GpsBrickletFunction::SetStatusCallbackPeriod => 9,
GpsBrickletFunction::GetStatusCallbackPeriod => 10,
GpsBrickletFunction::SetAltitudeCallbackPeriod => 11,
GpsBrickletFunction::GetAltitudeCallbackPeriod => 12,
GpsBrickletFunction::SetMotionCallbackPeriod => 13,
GpsBrickletFunction::GetMotionCallbackPeriod => 14,
GpsBrickletFunction::SetDateTimeCallbackPeriod => 15,
GpsBrickletFunction::GetDateTimeCallbackPeriod => 16,
GpsBrickletFunction::GetIdentity => 255,
GpsBrickletFunction::CallbackCoordinates => 17,
GpsBrickletFunction::CallbackStatus => 18,
GpsBrickletFunction::CallbackAltitude => 19,
GpsBrickletFunction::CallbackMotion => 20,
GpsBrickletFunction::CallbackDateTime => 21,
}
}
}
pub const GPS_BRICKLET_FIX_NO_FIX: u8 = 1;
pub const GPS_BRICKLET_FIX_2D_FIX: u8 = 2;
pub const GPS_BRICKLET_FIX_3D_FIX: u8 = 3;
pub const GPS_BRICKLET_RESTART_TYPE_HOT_START: u8 = 0;
pub const GPS_BRICKLET_RESTART_TYPE_WARM_START: u8 = 1;
pub const GPS_BRICKLET_RESTART_TYPE_COLD_START: u8 = 2;
pub const GPS_BRICKLET_RESTART_TYPE_FACTORY_RESET: u8 = 3;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Coordinates {
pub latitude: u32,
pub ns: char,
pub longitude: u32,
pub ew: char,
pub pdop: u16,
pub hdop: u16,
pub vdop: u16,
pub epe: u16,
}
impl FromByteSlice for Coordinates {
fn bytes_expected() -> usize { 18 }
fn from_le_byte_slice(bytes: &[u8]) -> Coordinates {
Coordinates {
latitude: <u32>::from_le_byte_slice(&bytes[0..4]),
ns: <char>::from_le_byte_slice(&bytes[4..5]),
longitude: <u32>::from_le_byte_slice(&bytes[5..9]),
ew: <char>::from_le_byte_slice(&bytes[9..10]),
pdop: <u16>::from_le_byte_slice(&bytes[10..12]),
hdop: <u16>::from_le_byte_slice(&bytes[12..14]),
vdop: <u16>::from_le_byte_slice(&bytes[14..16]),
epe: <u16>::from_le_byte_slice(&bytes[16..18]),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Status {
pub fix: u8,
pub satellites_view: u8,
pub satellites_used: u8,
}
impl FromByteSlice for Status {
fn bytes_expected() -> usize { 3 }
fn from_le_byte_slice(bytes: &[u8]) -> Status {
Status {
fix: <u8>::from_le_byte_slice(&bytes[0..1]),
satellites_view: <u8>::from_le_byte_slice(&bytes[1..2]),
satellites_used: <u8>::from_le_byte_slice(&bytes[2..3]),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Altitude {
pub altitude: i32,
pub geoidal_separation: i32,
}
impl FromByteSlice for Altitude {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> Altitude {
Altitude { altitude: <i32>::from_le_byte_slice(&bytes[0..4]), geoidal_separation: <i32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Motion {
pub course: u32,
pub speed: u32,
}
impl FromByteSlice for Motion {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> Motion {
Motion { course: <u32>::from_le_byte_slice(&bytes[0..4]), speed: <u32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct DateTime {
pub date: u32,
pub time: u32,
}
impl FromByteSlice for DateTime {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> DateTime {
DateTime { date: <u32>::from_le_byte_slice(&bytes[0..4]), time: <u32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct CoordinatesEvent {
pub latitude: u32,
pub ns: char,
pub longitude: u32,
pub ew: char,
pub pdop: u16,
pub hdop: u16,
pub vdop: u16,
pub epe: u16,
}
impl FromByteSlice for CoordinatesEvent {
fn bytes_expected() -> usize { 18 }
fn from_le_byte_slice(bytes: &[u8]) -> CoordinatesEvent {
CoordinatesEvent {
latitude: <u32>::from_le_byte_slice(&bytes[0..4]),
ns: <char>::from_le_byte_slice(&bytes[4..5]),
longitude: <u32>::from_le_byte_slice(&bytes[5..9]),
ew: <char>::from_le_byte_slice(&bytes[9..10]),
pdop: <u16>::from_le_byte_slice(&bytes[10..12]),
hdop: <u16>::from_le_byte_slice(&bytes[12..14]),
vdop: <u16>::from_le_byte_slice(&bytes[14..16]),
epe: <u16>::from_le_byte_slice(&bytes[16..18]),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct StatusEvent {
pub fix: u8,
pub satellites_view: u8,
pub satellites_used: u8,
}
impl FromByteSlice for StatusEvent {
fn bytes_expected() -> usize { 3 }
fn from_le_byte_slice(bytes: &[u8]) -> StatusEvent {
StatusEvent {
fix: <u8>::from_le_byte_slice(&bytes[0..1]),
satellites_view: <u8>::from_le_byte_slice(&bytes[1..2]),
satellites_used: <u8>::from_le_byte_slice(&bytes[2..3]),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct AltitudeEvent {
pub altitude: i32,
pub geoidal_separation: i32,
}
impl FromByteSlice for AltitudeEvent {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> AltitudeEvent {
AltitudeEvent { altitude: <i32>::from_le_byte_slice(&bytes[0..4]), geoidal_separation: <i32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct MotionEvent {
pub course: u32,
pub speed: u32,
}
impl FromByteSlice for MotionEvent {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> MotionEvent {
MotionEvent { course: <u32>::from_le_byte_slice(&bytes[0..4]), speed: <u32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct DateTimeEvent {
pub date: u32,
pub time: u32,
}
impl FromByteSlice for DateTimeEvent {
fn bytes_expected() -> usize { 8 }
fn from_le_byte_slice(bytes: &[u8]) -> DateTimeEvent {
DateTimeEvent { date: <u32>::from_le_byte_slice(&bytes[0..4]), time: <u32>::from_le_byte_slice(&bytes[4..8]) }
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct Identity {
pub uid: String,
pub connected_uid: String,
pub position: char,
pub hardware_version: [u8; 3],
pub firmware_version: [u8; 3],
pub device_identifier: u16,
}
impl FromByteSlice for Identity {
fn bytes_expected() -> usize { 25 }
fn from_le_byte_slice(bytes: &[u8]) -> Identity {
Identity {
uid: <String>::from_le_byte_slice(&bytes[0..8]),
connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
position: <char>::from_le_byte_slice(&bytes[16..17]),
hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
}
}
}
#[derive(Clone)]
pub struct GpsBricklet {
device: Device,
}
impl GpsBricklet {
pub const DEVICE_IDENTIFIER: u16 = 222;
pub const DEVICE_DISPLAY_NAME: &'static str = "GPS Bricklet";
pub fn new<T: GetRequestSender>(uid: &str, req_sender: T) -> GpsBricklet {
let mut result = GpsBricklet { device: Device::new([2, 0, 1], uid, req_sender, 0) };
result.device.response_expected[u8::from(GpsBrickletFunction::GetCoordinates) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::GetStatus) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::GetAltitude) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::GetMotion) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::GetDateTime) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::Restart) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(GpsBrickletFunction::SetCoordinatesCallbackPeriod) as usize] = ResponseExpectedFlag::True;
result.device.response_expected[u8::from(GpsBrickletFunction::GetCoordinatesCallbackPeriod) as usize] =
ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::SetStatusCallbackPeriod) as usize] = ResponseExpectedFlag::True;
result.device.response_expected[u8::from(GpsBrickletFunction::GetStatusCallbackPeriod) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::SetAltitudeCallbackPeriod) as usize] = ResponseExpectedFlag::True;
result.device.response_expected[u8::from(GpsBrickletFunction::GetAltitudeCallbackPeriod) as usize] =
ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::SetMotionCallbackPeriod) as usize] = ResponseExpectedFlag::True;
result.device.response_expected[u8::from(GpsBrickletFunction::GetMotionCallbackPeriod) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::SetDateTimeCallbackPeriod) as usize] = ResponseExpectedFlag::True;
result.device.response_expected[u8::from(GpsBrickletFunction::GetDateTimeCallbackPeriod) as usize] =
ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(GpsBrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
result
}
pub fn get_response_expected(&mut self, fun: GpsBrickletFunction) -> Result<bool, GetResponseExpectedError> {
self.device.get_response_expected(u8::from(fun))
}
pub fn set_response_expected(&mut self, fun: GpsBrickletFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
self.device.set_response_expected(u8::from(fun), response_expected)
}
pub fn set_response_expected_all(&mut self, response_expected: bool) { self.device.set_response_expected_all(response_expected) }
pub fn get_api_version(&self) -> [u8; 3] { self.device.api_version }
pub fn get_coordinates_callback_receiver(&self) -> ConvertingCallbackReceiver<CoordinatesEvent> {
self.device.get_callback_receiver(u8::from(GpsBrickletFunction::CallbackCoordinates))
}
pub fn get_status_callback_receiver(&self) -> ConvertingCallbackReceiver<StatusEvent> {
self.device.get_callback_receiver(u8::from(GpsBrickletFunction::CallbackStatus))
}
pub fn get_altitude_callback_receiver(&self) -> ConvertingCallbackReceiver<AltitudeEvent> {
self.device.get_callback_receiver(u8::from(GpsBrickletFunction::CallbackAltitude))
}
pub fn get_motion_callback_receiver(&self) -> ConvertingCallbackReceiver<MotionEvent> {
self.device.get_callback_receiver(u8::from(GpsBrickletFunction::CallbackMotion))
}
pub fn get_date_time_callback_receiver(&self) -> ConvertingCallbackReceiver<DateTimeEvent> {
self.device.get_callback_receiver(u8::from(GpsBrickletFunction::CallbackDateTime))
}
pub fn get_coordinates(&self) -> ConvertingReceiver<Coordinates> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetCoordinates), payload)
}
pub fn get_status(&self) -> ConvertingReceiver<Status> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetStatus), payload)
}
pub fn get_altitude(&self) -> ConvertingReceiver<Altitude> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetAltitude), payload)
}
pub fn get_motion(&self) -> ConvertingReceiver<Motion> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetMotion), payload)
}
pub fn get_date_time(&self) -> ConvertingReceiver<DateTime> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetDateTime), payload)
}
pub fn restart(&self, restart_type: u8) -> ConvertingReceiver<()> {
let mut payload = vec![0; 1];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(restart_type));
self.device.set(u8::from(GpsBrickletFunction::Restart), payload)
}
pub fn set_coordinates_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
self.device.set(u8::from(GpsBrickletFunction::SetCoordinatesCallbackPeriod), payload)
}
pub fn get_coordinates_callback_period(&self) -> ConvertingReceiver<u32> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetCoordinatesCallbackPeriod), payload)
}
pub fn set_status_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
self.device.set(u8::from(GpsBrickletFunction::SetStatusCallbackPeriod), payload)
}
pub fn get_status_callback_period(&self) -> ConvertingReceiver<u32> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetStatusCallbackPeriod), payload)
}
pub fn set_altitude_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
self.device.set(u8::from(GpsBrickletFunction::SetAltitudeCallbackPeriod), payload)
}
pub fn get_altitude_callback_period(&self) -> ConvertingReceiver<u32> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetAltitudeCallbackPeriod), payload)
}
pub fn set_motion_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
self.device.set(u8::from(GpsBrickletFunction::SetMotionCallbackPeriod), payload)
}
pub fn get_motion_callback_period(&self) -> ConvertingReceiver<u32> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetMotionCallbackPeriod), payload)
}
pub fn set_date_time_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
self.device.set(u8::from(GpsBrickletFunction::SetDateTimeCallbackPeriod), payload)
}
pub fn get_date_time_callback_period(&self) -> ConvertingReceiver<u32> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetDateTimeCallbackPeriod), payload)
}
pub fn get_identity(&self) -> ConvertingReceiver<Identity> {
let payload = vec![0; 0];
self.device.get(u8::from(GpsBrickletFunction::GetIdentity), payload)
}
}