mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
initial project
This commit is contained in:
parent
717006b1ec
commit
10c74910af
2
airportdisplay/.gitignore
vendored
Normal file
2
airportdisplay/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/Cargo.lock
|
8
airportdisplay/Cargo.toml
Normal file
8
airportdisplay/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "airportdisplay"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
"bytes" = "1.2"
|
||||||
|
|
26
airportdisplay/src/display/commands.rs
Normal file
26
airportdisplay/src/display/commands.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use super::window::Window;
|
||||||
|
|
||||||
|
/// Luminance value
|
||||||
|
pub struct Luminance(Window, u8);
|
||||||
|
|
||||||
|
/// TextRaw holds bytes and a window
|
||||||
|
pub struct TextRaw(pub Window, pub Vec<u8>);
|
||||||
|
|
||||||
|
/// TextBuffer holds a window an a text buffer
|
||||||
|
/// the text will be truncated to fit into the window
|
||||||
|
pub struct TextBuffer(pub Window, pub String);
|
||||||
|
|
||||||
|
/// Text Commands
|
||||||
|
pub enum Text {
|
||||||
|
Raw(TextRaw),
|
||||||
|
Buffer(TextBuffer),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Display Commands
|
||||||
|
pub enum Command {
|
||||||
|
Reset,
|
||||||
|
Clear,
|
||||||
|
Reboot,
|
||||||
|
Fadeout,
|
||||||
|
Text(Text),
|
||||||
|
}
|
6
airportdisplay/src/display/mod.rs
Normal file
6
airportdisplay/src/display/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pub mod commands;
|
||||||
|
pub mod protocol;
|
||||||
|
pub mod window;
|
||||||
|
|
||||||
|
pub const TEXT_COLUMNS: usize = 56;
|
||||||
|
pub const TEXT_ROWS: usize = 20;
|
79
airportdisplay/src/display/protocol.rs
Normal file
79
airportdisplay/src/display/protocol.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
use std::convert::From;
|
||||||
|
|
||||||
|
use bytes::BufMut;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
commands::{Command, Text, TextBuffer, TextRaw},
|
||||||
|
window::Window,
|
||||||
|
TEXT_COLUMNS, TEXT_ROWS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A frame holds a single encoded display command,
|
||||||
|
/// like set text at pos x, y.
|
||||||
|
type Frame = Vec<u8>;
|
||||||
|
|
||||||
|
/// Data is a list of commands to be sent to the display.
|
||||||
|
type Data = Vec<Frame>;
|
||||||
|
|
||||||
|
/// Encode window data
|
||||||
|
impl From<Window> for Frame {
|
||||||
|
fn from(Window { x, y, w, h }: Window) -> Self {
|
||||||
|
let mut buf = vec![];
|
||||||
|
buf.put_u16_le(x);
|
||||||
|
buf.put_u16_le(y);
|
||||||
|
buf.put_u16_le(w);
|
||||||
|
buf.put_u16_le(h);
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TextRaw> for Data {
|
||||||
|
fn from(TextRaw(window, bytes): TextRaw) -> Data {
|
||||||
|
let mut bytes = bytes.clone();
|
||||||
|
bytes.truncate(TEXT_COLUMNS);
|
||||||
|
vec![[vec![0x03, 0x00], window.into(), bytes].concat()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TextBuffer> for Data {
|
||||||
|
fn from(TextBuffer(window, text): TextBuffer) -> Data {
|
||||||
|
// let Window { x, y, w, h } = window;
|
||||||
|
let mut lines: Vec<&str> = text.split("\n").collect();
|
||||||
|
lines.truncate(TEXT_ROWS);
|
||||||
|
vec![vec![]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Text> for Data {
|
||||||
|
fn from(text: Text) -> Data {
|
||||||
|
match text {
|
||||||
|
Text::Raw(raw) => raw.into(),
|
||||||
|
Text::Buffer(buffer) => buffer.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode command
|
||||||
|
impl From<Command> for Data {
|
||||||
|
fn from(cmd: Command) -> Self {
|
||||||
|
match cmd {
|
||||||
|
Command::Reset => vec![vec![0x08, 0x00]],
|
||||||
|
Command::Clear => vec![vec![0x02, 0x00]],
|
||||||
|
Command::Reboot => vec![vec![0x0b, 0x00]],
|
||||||
|
Command::Fadeout => vec![vec![0x0d, 0x00]],
|
||||||
|
Command::Text(text) => text.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{Command, Data, Text, TextRaw, Window};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn frame_data_from_text_command() {
|
||||||
|
let cmd = Command::Text(Text::Raw(TextRaw(Window::position(1, 2), "text123".into())));
|
||||||
|
let data: Data = cmd.into();
|
||||||
|
println!("data: {:?}", data)
|
||||||
|
}
|
||||||
|
}
|
27
airportdisplay/src/display/window.rs
Normal file
27
airportdisplay/src/display/window.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/// A window for luminance and text commands
|
||||||
|
pub struct Window {
|
||||||
|
pub x: u16, // 0..55
|
||||||
|
pub y: u16, // 0..19
|
||||||
|
pub w: u16, // 1..56
|
||||||
|
pub h: u16, // 1..20
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn new(x: u16, y: u16, w: u16, h: u16) -> Self {
|
||||||
|
Window {
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
w: w,
|
||||||
|
h: h,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(x: u16, y: u16) -> Self {
|
||||||
|
Window {
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
w: 0,
|
||||||
|
h: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
airportdisplay/src/lib.rs
Normal file
3
airportdisplay/src/lib.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod display;
|
||||||
|
|
||||||
|
pub use display::commands::{Command, Text};
|
1
hello_display/.gitignore
vendored
Normal file
1
hello_display/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
30
hello_display/Cargo.lock
generated
Normal file
30
hello_display/Cargo.lock
generated
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "airportdisplay"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.62"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hello_display"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"airportdisplay",
|
||||||
|
"anyhow",
|
||||||
|
]
|
11
hello_display/Cargo.toml
Normal file
11
hello_display/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "hello_display"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
|
||||||
|
airportdisplay = { path = "../airportdisplay" }
|
||||||
|
|
16
hello_display/src/main.rs
Normal file
16
hello_display/src/main.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
println!("Sending hello display...");
|
||||||
|
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:17382")?;
|
||||||
|
|
||||||
|
|
||||||
|
for frame in frames {
|
||||||
|
socket.send_to(frame, "
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in a new issue