mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
added udp socket stuff
This commit is contained in:
parent
10c74910af
commit
4132c58020
|
@ -4,5 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
"bytes" = "1.2"
|
anyhow = "1"
|
||||||
|
bytes = "1.2"
|
||||||
|
codepage-437 = "0.1.0"
|
||||||
|
|
|
@ -1,4 +1,31 @@
|
||||||
use super::window::Window;
|
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Luminance value
|
/// Luminance value
|
||||||
pub struct Luminance(Window, u8);
|
pub struct Luminance(Window, u8);
|
||||||
|
@ -6,10 +33,27 @@ pub struct Luminance(Window, u8);
|
||||||
/// TextRaw holds bytes and a window
|
/// TextRaw holds bytes and a window
|
||||||
pub struct TextRaw(pub Window, pub Vec<u8>);
|
pub struct TextRaw(pub Window, pub Vec<u8>);
|
||||||
|
|
||||||
|
impl TextRaw {
|
||||||
|
pub fn new(x: u16, y: u16, bytes: Vec<u8>) -> Self {
|
||||||
|
Self(Window::position(x,y), bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// TextBuffer holds a window an a text buffer
|
/// TextBuffer holds a window an a text buffer
|
||||||
/// the text will be truncated to fit into the window
|
/// the text will be truncated to fit into the window
|
||||||
pub struct TextBuffer(pub Window, pub String);
|
pub struct TextBuffer(pub Window, pub String);
|
||||||
|
|
||||||
|
impl TextBuffer {
|
||||||
|
pub fn at(x: u16, y: u16, text: String) -> Self {
|
||||||
|
Self(Window::position(x,y), text)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from(text: String) -> Self {
|
||||||
|
Self::at(0, 0, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// Text Commands
|
/// Text Commands
|
||||||
pub enum Text {
|
pub enum Text {
|
||||||
Raw(TextRaw),
|
Raw(TextRaw),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
pub mod window;
|
|
||||||
|
|
||||||
pub const TEXT_COLUMNS: usize = 56;
|
pub const TEXT_COLUMNS: usize = 56;
|
||||||
pub const TEXT_ROWS: usize = 20;
|
pub const TEXT_ROWS: usize = 20;
|
||||||
|
|
|
@ -1,46 +1,59 @@
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
|
use codepage_437::{CP437_WINGDINGS, ToCp437};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
commands::{Command, Text, TextBuffer, TextRaw},
|
commands::{Command, Text, TextBuffer, TextRaw, Window},
|
||||||
window::Window,
|
|
||||||
TEXT_COLUMNS, TEXT_ROWS,
|
TEXT_COLUMNS, TEXT_ROWS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A frame holds a single encoded display command,
|
/// A frame holds a single encoded display command,
|
||||||
/// like set text at pos x, y.
|
/// like set text at pos x, y.
|
||||||
type Frame = Vec<u8>;
|
pub type Frame = Vec<u8>;
|
||||||
|
|
||||||
/// Data is a list of commands to be sent to the display.
|
/// Data is a list of commands to be sent to the display.
|
||||||
type Data = Vec<Frame>;
|
pub type Data = Vec<Frame>;
|
||||||
|
|
||||||
/// Encode window data
|
/// Encode window data
|
||||||
impl From<Window> for Frame {
|
impl From<Window> for Frame {
|
||||||
fn from(Window { x, y, w, h }: Window) -> Self {
|
fn from(Window { x, y, w, h }: Window) -> Self {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
buf.put_u16_le(x);
|
buf.put_u16(x);
|
||||||
buf.put_u16_le(y);
|
buf.put_u16(y);
|
||||||
buf.put_u16_le(w);
|
buf.put_u16(w);
|
||||||
buf.put_u16_le(h);
|
buf.put_u16(h);
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TextRaw> for Data {
|
impl From<TextRaw> for Data {
|
||||||
fn from(TextRaw(window, bytes): TextRaw) -> Data {
|
fn from(TextRaw(position, bytes): TextRaw) -> Data {
|
||||||
let mut bytes = bytes.clone();
|
let mut bytes = bytes.clone();
|
||||||
bytes.truncate(TEXT_COLUMNS);
|
bytes.truncate(TEXT_COLUMNS);
|
||||||
vec![[vec![0x03, 0x00], window.into(), bytes].concat()]
|
let window = Window::new(position.x, position.y, bytes.len() as u16, 1);
|
||||||
|
vec![[vec![0x00, 0x03], window.into(), bytes].concat()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TextBuffer> for Data {
|
impl From<TextBuffer> for Data {
|
||||||
fn from(TextBuffer(window, text): TextBuffer) -> Data {
|
fn from(TextBuffer(position, text): TextBuffer) -> Data {
|
||||||
// let Window { x, y, w, h } = window;
|
|
||||||
let mut lines: Vec<&str> = text.split("\n").collect();
|
let mut lines: Vec<&str> = text.split("\n").collect();
|
||||||
lines.truncate(TEXT_ROWS);
|
lines.truncate(TEXT_ROWS);
|
||||||
vec![vec![]]
|
|
||||||
|
let mut data = vec![];
|
||||||
|
for (i, line) in lines.iter().enumerate() {
|
||||||
|
if let Ok(bytes) = line.to_cp437(&CP437_WINGDINGS) {
|
||||||
|
let len = bytes.len() as u16;
|
||||||
|
let window = Window::new(position.x, position.y + i as u16, len as u16, 1);
|
||||||
|
data.push([
|
||||||
|
vec![0x00, 0x03],
|
||||||
|
window.into(),
|
||||||
|
bytes.into(),
|
||||||
|
].concat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,10 +70,10 @@ impl From<Text> for Data {
|
||||||
impl From<Command> for Data {
|
impl From<Command> for Data {
|
||||||
fn from(cmd: Command) -> Self {
|
fn from(cmd: Command) -> Self {
|
||||||
match cmd {
|
match cmd {
|
||||||
Command::Reset => vec![vec![0x08, 0x00]],
|
Command::Reset => vec![vec![0x00, 0x08]],
|
||||||
Command::Clear => vec![vec![0x02, 0x00]],
|
Command::Clear => vec![vec![0x00, 0x02]],
|
||||||
Command::Reboot => vec![vec![0x0b, 0x00]],
|
Command::Reboot => vec![vec![0x00, 0x0b]],
|
||||||
Command::Fadeout => vec![vec![0x0d, 0x00]],
|
Command::Fadeout => vec![vec![0x00, 0x0d]],
|
||||||
Command::Text(text) => text.into(),
|
Command::Text(text) => text.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/// 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,6 @@
|
||||||
mod display;
|
mod display;
|
||||||
|
mod net;
|
||||||
|
|
||||||
pub use display::commands::{Command, Text};
|
pub use display::commands::{Command, Text, TextRaw, TextBuffer, Window};
|
||||||
|
pub use display::protocol::Data;
|
||||||
|
pub use net::display::Display;
|
||||||
|
|
32
airportdisplay/src/net/display.rs
Normal file
32
airportdisplay/src/net/display.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
|
use crate::display::commands::Command;
|
||||||
|
use crate::display::protocol::Data;
|
||||||
|
|
||||||
|
pub struct Display {
|
||||||
|
addr: String,
|
||||||
|
socket: UdpSocket,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Display {
|
||||||
|
pub fn open(addr: String) -> Result<Self> {
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:17382")?;
|
||||||
|
Ok(Self{
|
||||||
|
addr: addr,
|
||||||
|
socket: socket,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&self, cmd: Command) -> Result<()> {
|
||||||
|
let data: Data = cmd.into();
|
||||||
|
for frame in data {
|
||||||
|
println!("sending payload: {:?}", &frame);
|
||||||
|
self.socket.send_to(frame.as_slice(), self.addr.clone().as_str())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
airportdisplay/src/net/mod.rs
Normal file
1
airportdisplay/src/net/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod display;
|
Loading…
Reference in a new issue