Started implementing the UDP protocol

This commit is contained in:
Thomas Kolb 2021-02-22 23:24:32 +01:00
parent ded8a7c21f
commit 7631bfb669
4 changed files with 156 additions and 7 deletions

View file

@ -10,3 +10,6 @@ pub const NUM_STRIPS: usize = 8;
pub const NUM_LEDS_PER_STRIP: usize = 16;
pub const NUM_LEDS_TOTAL: usize = NUM_STRIPS * NUM_LEDS_PER_STRIP;
// network configuration
pub const UDP_SERVER_ADDR: &str = "192.168.23.118:2703";

View file

@ -8,9 +8,11 @@ use byteorder::{NativeEndian, ReadBytesExt};
mod signal_processing;
mod config;
mod userscript;
mod udpproto;
use crate::signal_processing::SignalProcessing;
use crate::userscript::UserScript;
use crate::udpproto::UdpProto;
use std::rc::Rc;
use std::cell::RefCell;
@ -19,6 +21,15 @@ fn main()
{
let mut stdin = std::io::stdin();
// set up the UDP protocol
let mut udpproto = match UdpProto::new(config::UDP_SERVER_ADDR) {
Ok(u) => u,
Err(e) => {
println!("Error during UDP client setup:\n{}", e);
exit(1);
}
};
// set up signal processing
println!("Initializing signal processing...");
@ -30,7 +41,7 @@ fn main()
println!("Loading user script...");
let script = match UserScript::new(sigproc.clone(), "test.lua") {
let mut script = match UserScript::new(sigproc.clone(), "test.lua") {
Ok(script) => script,
Err(e) => {
println!("=== Lua Error ===\n{}\n====> Terminating.", e);
@ -98,6 +109,18 @@ fn main()
}
};
// FIXME: only send with 60 FPS!
for i in 0..script.colorlists[0].len() {
udpproto.set_color((i / config::NUM_LEDS_PER_STRIP) as u8,
(i % config::NUM_LEDS_PER_STRIP) as u8,
(script.colorlists[0][i] * 255.0) as u8,
(script.colorlists[1][i] * 255.0) as u8,
(script.colorlists[2][i] * 255.0) as u8,
(script.colorlists[3][i] * 255.0) as u8).unwrap();
}
udpproto.commit().unwrap();
}
}

119
src/udpproto.rs Normal file
View file

@ -0,0 +1,119 @@
// vim: noet
use std::net::UdpSocket;
use std::net::SocketAddrV4;
use std::net::Ipv4Addr;
const MAX_PACKET_LEN: usize = 1470;
struct Command
{
cmd: u8,
strip: u8,
led: u8,
data: [u8; 4],
}
pub struct UdpProto
{
socket: UdpSocket,
packet: [u8; MAX_PACKET_LEN],
packet_offset: usize,
}
impl UdpProto
{
pub fn new(target_address: &str) -> std::io::Result<UdpProto>
{
let u = UdpProto {
socket: UdpSocket::bind(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0))?,
packet: [0u8; MAX_PACKET_LEN],
packet_offset: 0,
};
u.socket.connect(target_address)?;
Ok(u)
}
fn send_packet(&mut self) -> std::io::Result<()>
{
if self.packet_offset == 0 {
// nothing to do
return Ok( () );
}
self.packet_offset = 0;
self.socket.send(&self.packet[0..self.packet_offset])?;
Ok( () )
}
fn add_command(&mut self, cmd: u8, strip: u8, led: u8, data: &[u8; 4]) -> std::io::Result<()>
{
// put the command into the packet buffer
self.packet[self.packet_offset + 0] = cmd;
self.packet[self.packet_offset + 1] = strip;
self.packet[self.packet_offset + 2] = led;
for i in 0 .. data.len() {
self.packet[self.packet_offset + i] = data[i];
}
self.packet_offset += 7;
if self.packet_offset >= MAX_PACKET_LEN {
self.send_packet()?;
}
Ok( () )
}
pub fn set_color(&mut self, strip: u8, led: u8,
r: u8, g: u8, b: u8, w: u8) -> std::io::Result<()>
{
let data = [r,g,b,w];
self.add_command(0x00, strip, led, &data)?;
Ok( () )
}
pub fn fade_color(&mut self, strip: u8, led: u8,
r: u8, g: u8, b: u8, w: u8) -> std::io::Result<()>
{
let data = [r,g,b,w];
self.add_command(0x01, strip, led, &data)?;
Ok( () )
}
pub fn add_color(&mut self, strip: u8, led: u8,
r: u8, g: u8, b: u8, w: u8) -> std::io::Result<()>
{
let data = [r,g,b,w];
self.add_command(0x02, strip, led, &data)?;
Ok( () )
}
pub fn set_fadestep(&mut self, fadestep: u8) -> std::io::Result<()>
{
let data = [fadestep, 0, 0, 0];
self.add_command(0x03, 0, 0, &data)?;
Ok( () )
}
pub fn commit(&mut self) -> std::io::Result<()>
{
// add the END_OF_UPDATE command
self.add_command(0xFE, 0, 0, &[0u8; 4])?;
self.send_packet()
}
}

View file

@ -33,6 +33,8 @@ use std::cell::RefCell;
pub struct UserScript
{
lua_state: Lua,
pub colorlists: [ [f32; config::NUM_LEDS_TOTAL]; 4],
}
impl UserScript
@ -41,6 +43,7 @@ impl UserScript
{
let s = UserScript {
lua_state: Lua::new(),
colorlists: [ [0f32; config::NUM_LEDS_TOTAL]; 4],
};
// provide some configuration constants to Lua via a table
@ -74,7 +77,7 @@ impl UserScript
Ok(())
}
pub fn periodic(&self) -> std::result::Result<(), mlua::Error>
pub fn periodic(&mut self) -> std::result::Result<(), mlua::Error>
{
// find the init functions
let lua_periodic_func: mlua::Function = self.lua_state.globals().get("periodic")?;
@ -89,8 +92,7 @@ impl UserScript
}
// convert the Lua Tables to normal vectors
let mut colorlists = Vec::<Vec<f32>>::new();
let mut i = 0;
for rval in rvals {
let table = mlua::Table::from_lua(rval, &self.lua_state)?;
@ -103,10 +105,12 @@ impl UserScript
return Err(Error::RuntimeError("Number of color values returned from 'periodic' must match number of LEDs given in 'init'.".to_string()));
}
colorlists.push(v);
}
for j in 0 .. self.colorlists[i].len() {
self.colorlists[i][j] = v[j];
}
println!("{:?}", colorlists[0][0]);
i += 1;
}
Ok(())
}