use crate::{
byte_converter::*,
converting_callback_receiver::ConvertingCallbackReceiver,
converting_receiver::{BrickletError, ConvertingReceiver},
device::*,
ip_connection::GetRequestSender,
};
pub enum Lcd20x4BrickletFunction {
WriteLine,
ClearDisplay,
BacklightOn,
BacklightOff,
IsBacklightOn,
SetConfig,
GetConfig,
IsButtonPressed,
SetCustomCharacter,
GetCustomCharacter,
SetDefaultText,
GetDefaultText,
SetDefaultTextCounter,
GetDefaultTextCounter,
GetIdentity,
CallbackButtonPressed,
CallbackButtonReleased,
}
impl From<Lcd20x4BrickletFunction> for u8 {
fn from(fun: Lcd20x4BrickletFunction) -> Self {
match fun {
Lcd20x4BrickletFunction::WriteLine => 1,
Lcd20x4BrickletFunction::ClearDisplay => 2,
Lcd20x4BrickletFunction::BacklightOn => 3,
Lcd20x4BrickletFunction::BacklightOff => 4,
Lcd20x4BrickletFunction::IsBacklightOn => 5,
Lcd20x4BrickletFunction::SetConfig => 6,
Lcd20x4BrickletFunction::GetConfig => 7,
Lcd20x4BrickletFunction::IsButtonPressed => 8,
Lcd20x4BrickletFunction::SetCustomCharacter => 11,
Lcd20x4BrickletFunction::GetCustomCharacter => 12,
Lcd20x4BrickletFunction::SetDefaultText => 13,
Lcd20x4BrickletFunction::GetDefaultText => 14,
Lcd20x4BrickletFunction::SetDefaultTextCounter => 15,
Lcd20x4BrickletFunction::GetDefaultTextCounter => 16,
Lcd20x4BrickletFunction::GetIdentity => 255,
Lcd20x4BrickletFunction::CallbackButtonPressed => 9,
Lcd20x4BrickletFunction::CallbackButtonReleased => 10,
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Config {
pub cursor: bool,
pub blinking: bool,
}
impl FromByteSlice for Config {
fn bytes_expected() -> usize { 2 }
fn from_le_byte_slice(bytes: &[u8]) -> Config {
Config { cursor: <bool>::from_le_byte_slice(&bytes[0..1]), blinking: <bool>::from_le_byte_slice(&bytes[1..2]) }
}
}
#[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 Lcd20x4Bricklet {
device: Device,
}
impl Lcd20x4Bricklet {
pub const DEVICE_IDENTIFIER: u16 = 212;
pub const DEVICE_DISPLAY_NAME: &'static str = "LCD 20x4 Bricklet";
pub fn new<T: GetRequestSender>(uid: &str, req_sender: T) -> Lcd20x4Bricklet {
let mut result = Lcd20x4Bricklet { device: Device::new([2, 0, 2], uid, req_sender, 0) };
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::WriteLine) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::ClearDisplay) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::BacklightOn) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::BacklightOff) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::IsBacklightOn) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::SetConfig) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::GetConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::IsButtonPressed) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::SetCustomCharacter) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::GetCustomCharacter) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::SetDefaultText) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::GetDefaultText) as usize] = ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::SetDefaultTextCounter) as usize] = ResponseExpectedFlag::False;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::GetDefaultTextCounter) as usize] =
ResponseExpectedFlag::AlwaysTrue;
result.device.response_expected[u8::from(Lcd20x4BrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
result
}
pub fn get_response_expected(&mut self, fun: Lcd20x4BrickletFunction) -> Result<bool, GetResponseExpectedError> {
self.device.get_response_expected(u8::from(fun))
}
pub fn set_response_expected(&mut self, fun: Lcd20x4BrickletFunction, 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_button_pressed_callback_receiver(&self) -> ConvertingCallbackReceiver<u8> {
self.device.get_callback_receiver(u8::from(Lcd20x4BrickletFunction::CallbackButtonPressed))
}
pub fn get_button_released_callback_receiver(&self) -> ConvertingCallbackReceiver<u8> {
self.device.get_callback_receiver(u8::from(Lcd20x4BrickletFunction::CallbackButtonReleased))
}
pub fn write_line(&self, line: u8, position: u8, text: String) -> ConvertingReceiver<()> {
let mut payload = vec![0; 22];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(line));
payload[1..2].copy_from_slice(&<u8>::to_le_byte_vec(position));
match <String>::try_to_le_byte_vec(text, 20) {
Err(e) => {
let (tx, rx) = std::sync::mpsc::channel::<Result<Vec<u8>, BrickletError>>();
let _ = tx.send(Err(e));
return ConvertingReceiver::new(rx, std::time::Duration::new(1, 0));
}
Ok(bytes) => payload[2..22].copy_from_slice(&bytes),
}
self.device.set(u8::from(Lcd20x4BrickletFunction::WriteLine), payload)
}
pub fn clear_display(&self) -> ConvertingReceiver<()> {
let payload = vec![0; 0];
self.device.set(u8::from(Lcd20x4BrickletFunction::ClearDisplay), payload)
}
pub fn backlight_on(&self) -> ConvertingReceiver<()> {
let payload = vec![0; 0];
self.device.set(u8::from(Lcd20x4BrickletFunction::BacklightOn), payload)
}
pub fn backlight_off(&self) -> ConvertingReceiver<()> {
let payload = vec![0; 0];
self.device.set(u8::from(Lcd20x4BrickletFunction::BacklightOff), payload)
}
pub fn is_backlight_on(&self) -> ConvertingReceiver<bool> {
let payload = vec![0; 0];
self.device.get(u8::from(Lcd20x4BrickletFunction::IsBacklightOn), payload)
}
pub fn set_config(&self, cursor: bool, blinking: bool) -> ConvertingReceiver<()> {
let mut payload = vec![0; 2];
payload[0..1].copy_from_slice(&<bool>::to_le_byte_vec(cursor));
payload[1..2].copy_from_slice(&<bool>::to_le_byte_vec(blinking));
self.device.set(u8::from(Lcd20x4BrickletFunction::SetConfig), payload)
}
pub fn get_config(&self) -> ConvertingReceiver<Config> {
let payload = vec![0; 0];
self.device.get(u8::from(Lcd20x4BrickletFunction::GetConfig), payload)
}
pub fn is_button_pressed(&self, button: u8) -> ConvertingReceiver<bool> {
let mut payload = vec![0; 1];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(button));
self.device.get(u8::from(Lcd20x4BrickletFunction::IsButtonPressed), payload)
}
pub fn set_custom_character(&self, index: u8, character: [u8; 8]) -> ConvertingReceiver<()> {
let mut payload = vec![0; 9];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(index));
payload[1..9].copy_from_slice(&<[u8; 8]>::to_le_byte_vec(character));
self.device.set(u8::from(Lcd20x4BrickletFunction::SetCustomCharacter), payload)
}
pub fn get_custom_character(&self, index: u8) -> ConvertingReceiver<[u8; 8]> {
let mut payload = vec![0; 1];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(index));
self.device.get(u8::from(Lcd20x4BrickletFunction::GetCustomCharacter), payload)
}
pub fn set_default_text(&self, line: u8, text: String) -> ConvertingReceiver<()> {
let mut payload = vec![0; 21];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(line));
match <String>::try_to_le_byte_vec(text, 20) {
Err(e) => {
let (tx, rx) = std::sync::mpsc::channel::<Result<Vec<u8>, BrickletError>>();
let _ = tx.send(Err(e));
return ConvertingReceiver::new(rx, std::time::Duration::new(1, 0));
}
Ok(bytes) => payload[1..21].copy_from_slice(&bytes),
}
self.device.set(u8::from(Lcd20x4BrickletFunction::SetDefaultText), payload)
}
pub fn get_default_text(&self, line: u8) -> ConvertingReceiver<String> {
let mut payload = vec![0; 1];
payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(line));
self.device.get(u8::from(Lcd20x4BrickletFunction::GetDefaultText), payload)
}
pub fn set_default_text_counter(&self, counter: i32) -> ConvertingReceiver<()> {
let mut payload = vec![0; 4];
payload[0..4].copy_from_slice(&<i32>::to_le_byte_vec(counter));
self.device.set(u8::from(Lcd20x4BrickletFunction::SetDefaultTextCounter), payload)
}
pub fn get_default_text_counter(&self) -> ConvertingReceiver<i32> {
let payload = vec![0; 0];
self.device.get(u8::from(Lcd20x4BrickletFunction::GetDefaultTextCounter), payload)
}
pub fn get_identity(&self) -> ConvertingReceiver<Identity> {
let payload = vec![0; 0];
self.device.get(u8::from(Lcd20x4BrickletFunction::GetIdentity), payload)
}
}