From 08b1b92f520a7714a155eb662f7743f663ed4f5a Mon Sep 17 00:00:00 2001 From: 4yn Date: Tue, 22 Feb 2022 21:55:39 +0800 Subject: [PATCH] hook with slider --- src-slider_io/src/bin/test_diva.rs | 7 ++++-- src-slider_io/src/device/diva.rs | 31 ++++++++++++++++++++------ src-slider_io/src/shared/worker.rs | 2 ++ src-wwserial/include/wwserial.h | 6 ++--- src-wwserial/src/bin/test_handshake.rs | 24 ++++++++++++++++---- src-wwserial/src/lib.rs | 19 +++++++++++----- src-wwserial/src/serial_win.cc | 7 +++++- src-wwserial/src/wwserial.cc | 18 ++++++++------- 8 files changed, 83 insertions(+), 31 deletions(-) diff --git a/src-slider_io/src/bin/test_diva.rs b/src-slider_io/src/bin/test_diva.rs index 9d82900..ff2158c 100644 --- a/src-slider_io/src/bin/test_diva.rs +++ b/src-slider_io/src/bin/test_diva.rs @@ -1,6 +1,9 @@ extern crate slider_io; -use std::io; +use std::{ + io, + time::{Duration, Instant}, +}; use slider_io::{device::diva, shared::worker::ThreadJob, state::SliderState}; @@ -10,7 +13,7 @@ fn main() { .init(); let state = SliderState::new(); - let mut job = diva::DivaSliderJob::new(&state, &"COM3".to_string(), 0x3f); + let mut job = diva::DivaSliderJob::new(&state, &"COM1".to_string(), 0x3f); let ok = job.setup(); while ok { diff --git a/src-slider_io/src/device/diva.rs b/src-slider_io/src/device/diva.rs index 8dfc529..e08b5f4 100644 --- a/src-slider_io/src/device/diva.rs +++ b/src-slider_io/src/device/diva.rs @@ -1,5 +1,8 @@ -use log::{error, info, warn}; // debug -use std::collections::VecDeque; //thread::sleep, time::Duration +use log::{debug, error, info, warn}; +use std::{ + collections::VecDeque, + time::{Duration, Instant}, +}; // thread::sleep, time::Duration use wwserial::WwSerial; use crate::{shared::worker::ThreadJob, state::SliderState}; @@ -197,6 +200,7 @@ pub struct DivaSliderJob { deserializer: DivaDeserializer, serial_port: Option, bootstrap: DivaSliderBootstrap, + last_lights: Instant, } impl DivaSliderJob { @@ -211,6 +215,7 @@ impl DivaSliderJob { deserializer: DivaDeserializer::new(), serial_port: None, bootstrap: DivaSliderBootstrap::Init, + last_lights: Instant::now(), } } } @@ -223,7 +228,7 @@ impl ThreadJob for DivaSliderJob { 115200 ); - let serial_port = WwSerial::new(self.port.clone(), 115200, 10, true); + let serial_port = WwSerial::new(self.port.clone(), 115200, 5, 0, false); if !serial_port.check() { error!("Cannot open serial port at {}", self.port.as_str()); return false; @@ -238,9 +243,9 @@ impl ThreadJob for DivaSliderJob { let serial_port = self.serial_port.as_mut().unwrap(); self.read_buf.clear(); - let read_amount = serial_port.read(&mut self.read_buf, 1024) as usize; + let read_amount = serial_port.read(&mut self.read_buf) as usize; if read_amount > 0 { - // debug!("Serial read {} bytes", read_amount); + debug!("Serial read {} bytes", read_amount); self .deserializer .deserialize(&self.read_buf[0..read_amount], &mut self.in_packets); @@ -285,6 +290,7 @@ impl ThreadJob for DivaSliderJob { let start_packet = DivaPacket::from_bytes(0x03, &[]); self.out_packets.push_back(start_packet); self.bootstrap = DivaSliderBootstrap::ReadLoop; + self.last_lights = Instant::now(); } } DivaSliderBootstrap::ReadLoop => { @@ -302,7 +308,8 @@ impl ThreadJob for DivaSliderJob { let mut lights_buf = [0; 94]; { let mut lights_handle = self.state.lights.lock(); - if lights_handle.dirty { + // Send leds at least once a second to keep alive + if lights_handle.dirty || self.last_lights.elapsed() > Duration::from_millis(1000) { send_lights = true; lights_buf[0] = self.brightness; lights_buf[1..94].copy_from_slice(&lights_handle.ground[0..93]); @@ -311,16 +318,26 @@ impl ThreadJob for DivaSliderJob { } if send_lights { + self.last_lights = Instant::now(); let lights_packet = DivaPacket::from_bytes(0x02, &lights_buf); self.out_packets.push_back(lights_packet); } } }; + // sleep(Duration::from_millis(3)); while let Some(mut packet) = self.out_packets.pop_front() { - serial_port.write(packet.serialize()); + work = true; + let data = packet.serialize(); + let bytes_written = serial_port.write(data); + if bytes_written == 0 { + warn!("Serial write timeout"); + } + debug!("Serial write {}/{}", bytes_written, data.len()); } + // sleep(Duration::from_millis(3)); + // TODO: async worker? // sleep(Duration::from_millis(10)); diff --git a/src-slider_io/src/shared/worker.rs b/src-slider_io/src/shared/worker.rs index f3508c4..35f382b 100644 --- a/src-slider_io/src/shared/worker.rs +++ b/src-slider_io/src/shared/worker.rs @@ -82,6 +82,8 @@ impl AsyncWorker { where T: AsyncJob, { + info!("Async worker starting {}", name); + let stop_signal = Arc::new(AtomicBool::new(false)); let stop_signal_clone = Arc::clone(&stop_signal); diff --git a/src-wwserial/include/wwserial.h b/src-wwserial/include/wwserial.h index 423183b..132a2f1 100644 --- a/src-wwserial/include/wwserial.h +++ b/src-wwserial/include/wwserial.h @@ -6,11 +6,11 @@ struct CxxSerial { - CxxSerial(rust::String port, uint32_t baud, uint32_t timeout, bool hardware); + CxxSerial(rust::String port, uint32_t baud, uint32_t read_timeout, uint32_t write_timeout, bool hardware); uint32_t write(const rust::Vec &data) const; - uint32_t read(rust::Vec &data, uint32_t cap) const; + uint32_t read(rust::Vec &data) const; void flush() const; @@ -22,4 +22,4 @@ private: }; // port: String, baud: u32, timeout: u32, hardware: bool -std::unique_ptr new_cxx_serial(rust::String port, uint32_t baud, uint32_t timeout, bool hardware); \ No newline at end of file +std::unique_ptr new_cxx_serial(rust::String port, uint32_t baud, uint32_t read_timeout, uint32_t write_timeout, bool hardware); \ No newline at end of file diff --git a/src-wwserial/src/bin/test_handshake.rs b/src-wwserial/src/bin/test_handshake.rs index 2144ed7..3ba656a 100644 --- a/src-wwserial/src/bin/test_handshake.rs +++ b/src-wwserial/src/bin/test_handshake.rs @@ -3,7 +3,7 @@ extern crate wwserial; use wwserial::WwSerial; fn main() { - let s = WwSerial::new("COM3".to_string(), 115200, 1000, true); + let s = WwSerial::new("COM3".to_string(), 115200, 20, 20, true); let x: Vec = vec![0xff, 0x10, 0x00, 0xf1]; println!("Sending {:?}", x); @@ -11,7 +11,7 @@ fn main() { println!("Sent {}/4", bytes); let mut r: Vec = Vec::with_capacity(100); - s.read(&mut r, 100); + s.read(&mut r); println!("Received {:?}", r); let x: Vec = vec![0xff, 0xf0, 0x00, 0x11]; @@ -20,7 +20,7 @@ fn main() { println!("Sent {}/4", bytes); let mut r: Vec = Vec::with_capacity(100); - s.read(&mut r, 100); + s.read(&mut r); println!("Received {:?}", r); let x: Vec = vec![0xff, 0x03, 0x00, 0xfe]; @@ -28,12 +28,28 @@ fn main() { let bytes = s.write(&x); println!("Sent {}/4", bytes); + let mut r: Vec = Vec::with_capacity(100); + s.read(&mut r); + println!("Received {:?}", r); + + let x: Vec = vec![0xff; 130]; + println!("Sending {:?}", x); + let bytes = s.write(&x); + println!("Sent {}/130", bytes); + println!("Infinite looping, ctrl-c to quit"); loop { let mut r: Vec = Vec::with_capacity(500); - let bytes = s.read(&mut r, 500); + let bytes = s.read(&mut r); if bytes > 0 { println!("(ctrl-c to quit) Received ({}) {:?}", bytes, r); + + { + let x: Vec = vec![0xff; 130]; + println!("Sending {:?}", x); + let bytes = s.write(&x); + println!("Sent {}/130", bytes); + } } } } diff --git a/src-wwserial/src/lib.rs b/src-wwserial/src/lib.rs index 32b84ef..ed367b6 100644 --- a/src-wwserial/src/lib.rs +++ b/src-wwserial/src/lib.rs @@ -8,13 +8,14 @@ mod ffi { fn new_cxx_serial( port: String, baud: u32, - timeout: u32, + read_timeout: u32, + write_timeout: u32, hardware: bool, ) -> UniquePtr; fn write(self: &CxxSerial, data: &Vec) -> u32; - fn read(self: &CxxSerial, data: &mut Vec, cap: u32) -> u32; + fn read(self: &CxxSerial, data: &mut Vec) -> u32; fn flush(self: &CxxSerial); @@ -31,9 +32,15 @@ pub struct WwSerial { unsafe impl Send for WwSerial {} impl WwSerial { - pub fn new(port: String, baud: u32, timeout: u32, hardware: bool) -> Self { + pub fn new( + port: String, + baud: u32, + read_timeout: u32, + write_timeout: u32, + hardware: bool, + ) -> Self { Self { - inner: new_cxx_serial(port, baud, timeout, hardware), + inner: new_cxx_serial(port, baud, read_timeout, write_timeout, hardware), } } @@ -43,8 +50,8 @@ impl WwSerial { } // #[inline(always)] - pub fn read(&self, data: &mut Vec, cap: u32) -> u32 { - self.inner.read(data, cap) + pub fn read(&self, data: &mut Vec) -> u32 { + self.inner.read(data) } // #[inline(always)] diff --git a/src-wwserial/src/serial_win.cc b/src-wwserial/src/serial_win.cc index b9acce7..9d0ec66 100644 --- a/src-wwserial/src/serial_win.cc +++ b/src-wwserial/src/serial_win.cc @@ -351,8 +351,13 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length) } DWORD bytes_written; if (!WriteFile(fd_, data, static_cast(length), &bytes_written, NULL)) { + DWORD errcode = GetLastError(); + if (errcode == 121) { + // Timeout + return 0; + } stringstream ss; - ss << "Error while writing to the serial port: " << GetLastError(); + ss << "Error while writing to the serial port: " << errcode; THROW (IOException, ss.str().c_str()); } return (size_t) (bytes_written); diff --git a/src-wwserial/src/wwserial.cc b/src-wwserial/src/wwserial.cc index 9971d3c..04cfe34 100644 --- a/src-wwserial/src/wwserial.cc +++ b/src-wwserial/src/wwserial.cc @@ -3,6 +3,7 @@ #include "wwserial/src/lib.rs.h" #include +#include struct CxxSerial::impl { @@ -16,7 +17,7 @@ struct CxxSerial::impl CxxSerial::impl::impl() : serial_port(nullptr){}; -CxxSerial::CxxSerial(rust::String port, uint32_t baud, uint32_t timeout, bool hardware) +CxxSerial::CxxSerial(rust::String port, uint32_t baud, uint32_t read_timeout, uint32_t write_timeout, bool hardware) : impl(new struct CxxSerial::impl) { impl->ok = true; @@ -24,7 +25,7 @@ CxxSerial::CxxSerial(rust::String port, uint32_t baud, uint32_t timeout, bool ha try { impl->serial_port = std::shared_ptr( - new class serial::Serial(port_stdstring, baud, serial::Timeout::simpleTimeout(timeout))); + new class serial::Serial(port_stdstring, baud, serial::Timeout(1, read_timeout, 0, write_timeout, 0))); if (hardware) { impl->serial_port->setFlowcontrol(serial::flowcontrol_hardware); @@ -41,18 +42,19 @@ uint32_t CxxSerial::write(const rust::Vec &data) const if (impl->ok && impl->serial_port->isOpen()) { std::vector buf(data.begin(), data.end()); - return impl->serial_port->write(buf); + size_t bytes_written = impl->serial_port->write(buf); + return bytes_written; } return 0; }; -uint32_t CxxSerial::read(rust::Vec &data, uint32_t cap) const +uint32_t CxxSerial::read(rust::Vec &data) const { if (impl->ok && impl->serial_port->isOpen()) { std::vector buf; - buf.reserve(cap); - size_t bytes_read = impl->serial_port->read(buf, (size_t)cap); + buf.reserve(data.capacity()); + size_t bytes_read = impl->serial_port->read(buf, (size_t)buf.capacity()); std::copy( buf.begin(), buf.end(), std::back_inserter(data)); @@ -74,7 +76,7 @@ bool CxxSerial::check() const return impl->ok; } -std::unique_ptr new_cxx_serial(rust::String port, uint32_t baud, uint32_t timeout, bool hardware) +std::unique_ptr new_cxx_serial(rust::String port, uint32_t baud, uint32_t read_timeout, uint32_t write_timeout, bool hardware) { - return std::make_unique(port, baud, timeout, hardware); + return std::make_unique(port, baud, read_timeout, write_timeout, hardware); }