diff --git a/script/cpu-net-monitor.py b/script/cpu-net-monitor.py index 4234448..d78f849 100755 --- a/script/cpu-net-monitor.py +++ b/script/cpu-net-monitor.py @@ -8,6 +8,8 @@ from time import sleep import serial import psutil +BAR_MAX_HEIGHT = 255 + class State: run: bool device: str @@ -36,6 +38,7 @@ class State: await self._loop.run_in_executor(None, self.port.write, pkt) except serial.SerialException as e: logging.error("[!] Error operating with device: %s", str(e)) + await asyncio.sleep(30) except Exception as e: logging.exception("unhandled exception") self.run = False @@ -47,42 +50,50 @@ class State: rx = 0 tx = 0 while self.run: - cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 1, True) - load = [ int(((x/100) **2) * 255) for x in cpu_report ] # mypy whines but percpu returns a list + cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 0.1, True) net = psutil.net_io_counters(pernic=True) d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo") d_tx = sum(v.bytes_sent for k, v in net.items() if k != "lo") - await self.packets.put(struct.pack("BBBBBBBB", 3, 6, *load, min(int((d_tx - tx) / 1000), 255), min(int((d_rx - rx) / 1000), 255))) + p_rx = min(int(d_rx - rx), 255) + p_tx = min(int(d_tx - tx), 255) + w_rx = min(int((d_rx - rx) / 4096), 255) + w_tx = min(int((d_tx - tx) / 4096), 255) + await self.packets.put(struct.pack("BBBBBB", 1, 4, *( int(((x/100) **2) * BAR_MAX_HEIGHT) for x in cpu_report ))) + await self.packets.put(struct.pack("BBBB", 2, 2, min(int((d_tx - tx) / 1024), BAR_MAX_HEIGHT), min(int((d_rx - rx) / 1024), 255))) + await self.packets.put(struct.pack("BBBBBBBBBB", 3, 8, *( int((x/100) * BAR_MAX_HEIGHT) for x in cpu_report ), p_tx, p_rx, w_tx, w_rx)) rx = d_rx tx = d_tx - async def cpu_load_leds(self): - while self.run: - cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 0.05, True) - load = [ int(((x/100) **2) * 255) for x in cpu_report ] # mypy whines but percpu returns a list - logging.info("CPU [%d|%d|%d|%d]", *load) - await self.packets.put(struct.pack("BBBBBB", 1, 4, *load)) + # async def cpu_load_leds(self): + # return + # while self.run: + # cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 0.05, True) + # load = [ int(((x/100) **2) * 255) for x in cpu_report ] # mypy whines but percpu returns a list + # logging.info("CPU [%d|%d|%d|%d]", *load) + # await self.packets.put(struct.pack("BBBBBB", 1, 4, *load)) - async def net_traffic_leds(self): - rx = 0 - tx = 0 - while self.run: - net = psutil.net_io_counters(pernic=True) - d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo") - d_tx = sum(v.bytes_sent for k, v in net.items() if k != "lo") - logging.info("NET [TX %d | %d RX]", d_tx - tx, d_rx - rx) - await self.packets.put(struct.pack("BBBB", 2, 2, min(d_tx - tx, 255), min(d_rx - rx, 255))) - rx = d_rx - tx = d_tx - await asyncio.sleep(0.01) + # async def net_traffic_leds(self): + # return + # rx = 0 + # tx = 0 + # while self.run: + # net = psutil.net_io_counters(pernic=True) + # d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo") + # d_tx = sum(v.bytes_sent for k, v in net.items() if k != "lo") + # logging.info("NET [TX %d | %d RX]", d_tx - tx, d_rx - rx) + # await self.packets.put(struct.pack("BBBB", 2, 2, min(d_tx - tx, 255), min(d_rx - rx, 255))) + # rx = d_rx + # tx = d_tx + # await asyncio.sleep(0.01) async def run_tasks(self): self._loop = asyncio.get_event_loop() port_manager = self._loop.create_task(self.run_port_manager()) - cpu_leds = self._loop.create_task(self.cpu_load_leds()) - net_leds = self._loop.create_task(self.net_traffic_leds()) + # cpu_leds = self._loop.create_task(self.cpu_load_leds()) + # net_leds = self._loop.create_task(self.net_traffic_leds()) display = self._loop.create_task(self.display_polling()) - await asyncio.gather(port_manager, cpu_leds, net_leds, display) + # await asyncio.gather(port_manager, cpu_leds, net_leds, display) + await asyncio.gather(port_manager, display) if __name__ == "__main__": if len(sys.argv) < 2: @@ -91,7 +102,7 @@ if __name__ == "__main__": logging.basicConfig(level=logging.WARNING) - state = State(sys.argv[1]) + state = State(sys.argv[1], baudrate=115200) asyncio.run(state.run_tasks()) diff --git a/src/display.rs b/src/display.rs index 9cc3136..829aafd 100644 --- a/src/display.rs +++ b/src/display.rs @@ -37,6 +37,17 @@ fn byte_to_height(val: u8, max: u8) -> u32 { // return ((val as f32 / 255.0) * max as f32) as u32; // TODO get rid of floating point operations! } +pub fn _draw_number_as_box(display: &mut Display, value: u32, width: u32, height: u32, base_x: u32, base_y: u32) { + let mut i = 0; + for x in 0..width { + for y in 0..height { + display.set_pixel(base_x + x, base_y + y, ((value << i) & 1) == 1); + i = (i + i) % 32; + } + } + +} + pub fn draw_ui(display: &mut Display, style: &DisplayStyle) { Rectangle::new(Point::new(0, 0), Size::new(85, 64)) .into_styled(style.border_style) @@ -51,10 +62,10 @@ pub fn draw_ui(display: &mut Display, style: &DisplayStyle) { // since my specific display is 2 displays of different colors joined, there's a small gap // between pixels 19 and 20. This makes the 2 extra blank pixels look bad, so I'm removing 3. // On normal screens this will look worse and you should put them back. - // Rectangle::new(Point::new(87, 16), Size::new(11, 48)) - // .into_styled(style.border_style) - // .draw(display) - // .unwrap(); + Rectangle::new(Point::new(87, 16), Size::new(11, 48)) + .into_styled(style.border_style) + .draw(display) + .unwrap(); Rectangle::new(Point::new(100, 0), Size::new(28, 64)) .into_styled(style.border_style) @@ -87,20 +98,29 @@ pub enum NetDirection { TX, RX } -pub fn draw_network_bar(display: &mut Display, direction: NetDirection, value: u8, style: &DisplayStyle) { +pub fn draw_network_bar(display: &mut Display, direction: NetDirection, value_fine: u8, value_wide: u8, style: &DisplayStyle) { let x = match direction { NetDirection::TX => 103, NetDirection::RX => 115 }; - let height = byte_to_height(value, 54); - Rectangle::new(Point::new(x as i32, 8), Size::new(10, 54 - (height-1) as u32)) + let height_fine = byte_to_height(value_fine, 54); + let height_wide = byte_to_height(value_wide, 54); + Rectangle::new(Point::new(x as i32, 8), Size::new(2, 54 - (height_fine-1) as u32)) .into_styled(style.background_style) .draw(display) .unwrap(); - Rectangle::new(Point::new(x as i32, (62 - height) as i32), Size::new(10, 1 + height as u32)) + Rectangle::new(Point::new(x as i32, (62 - height_fine) as i32), Size::new(2, 1 + height_fine as u32)) + .into_styled(style.bar_style) + .draw(display) + .unwrap(); + Rectangle::new(Point::new(3 + x as i32, 8), Size::new(7, 54 - (height_wide-1) as u32)) + .into_styled(style.background_style) + .draw(display) + .unwrap(); + Rectangle::new(Point::new(3 + x as i32, (62 - height_wide) as i32), Size::new(7, 1 + height_wide as u32)) .into_styled(style.bar_style) .draw(display) .unwrap(); } -fn _draw_all(display: &mut Display, cpu1: u8, cpu2: u8, cpu3: u8, cpu4: u8, tx: u8, rx: u8, style: &DisplayStyle) { +fn _draw_all(display: &mut Display, cpu1: u8, cpu2: u8, cpu3: u8, cpu4: u8, tx: u8, rx: u8, tx_wide:u8, rx_wide: u8, style: &DisplayStyle) { draw_ui(display, style); draw_cpu_bar(display, 1, cpu1, style); @@ -108,8 +128,8 @@ fn _draw_all(display: &mut Display, cpu1: u8, cpu2: u8, cpu3: u8, cpu4: u8, tx: draw_cpu_bar(display, 3, cpu3, style); draw_cpu_bar(display, 4, cpu4, style); - draw_network_bar(display, NetDirection::TX, tx, style); - draw_network_bar(display, NetDirection::RX, rx, style); + draw_network_bar(display, NetDirection::TX, tx, tx_wide, style); + draw_network_bar(display, NetDirection::RX, rx, rx_wide, style); display.flush().unwrap(); } diff --git a/src/main.rs b/src/main.rs index ce94109..b4d4242 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ mod display; use crate::packet::PacketBuilder; use crate::utils::FourLedDisplay; -use display::{draw_ui, draw_cpu_bar, draw_network_bar, NetDirection}; +use display::{draw_ui, draw_cpu_bar, draw_network_bar, NetDirection, Spinner}; pub struct DisplayStyle<'a> { border_style: PrimitiveStyle, @@ -41,10 +41,10 @@ fn main() -> ! { let mut led_tx = pins.d4.into_output(); // red let button = pins.d2.into_pull_up_input(); let mut cpu_leds = FourLedDisplay::new( - pins.d3.into_output().into_pwm(&timer2), - pins.d9.into_output().into_pwm(&timer1), - pins.d10.into_output().into_pwm(&timer1), pins.d11.into_output().into_pwm(&timer2), + pins.d10.into_output().into_pwm(&timer1), + pins.d9.into_output().into_pwm(&timer1), + pins.d3.into_output().into_pwm(&timer2), ); let i2c = arduino_hal::i2c::I2c::new( dp.TWI, pins.a4.into_pull_up_input(), pins.a5.into_pull_up_input(), 800000 @@ -75,6 +75,7 @@ fn main() -> ! { // prepare display let interface = I2CDisplayInterface::new(i2c); let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0).into_buffered_graphics_mode(); + let mut s = Spinner::new(91, 10); display.init().unwrap(); cpu_leds.set(1, 255); @@ -124,13 +125,14 @@ fn main() -> ! { } }, PacketId::ScreenDrawPacket => { - if let Some(payload) = pkt.payload && payload.len() == 6 { + if let Some(payload) = pkt.payload && payload.len() == 8 { + s.draw(&mut display); draw_cpu_bar(&mut display, 1, payload[0], &style); draw_cpu_bar(&mut display, 2, payload[1], &style); draw_cpu_bar(&mut display, 3, payload[2], &style); draw_cpu_bar(&mut display, 4, payload[3], &style); - draw_network_bar(&mut display, NetDirection::TX, payload[4], &style); - draw_network_bar(&mut display, NetDirection::RX, payload[5], &style); + draw_network_bar(&mut display, NetDirection::TX, payload[4], payload[6], &style); + draw_network_bar(&mut display, NetDirection::RX, payload[5], payload[7], &style); display.flush().unwrap(); } }, diff --git a/src/utils.rs b/src/utils.rs index 1db7f1e..82bee80 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,18 +2,18 @@ use arduino_hal::{simple_pwm::*, port::{Pin, mode::PwmOutput}, hal::port::{PD3, // TODO can I make it a generic "Pin" and use a slice? pub struct FourLedDisplay { - led1: Pin, PD3>, - led2: Pin, PB1>, - led3: Pin, PB2>, - led4: Pin, PB3>, + led1: Pin, PB3>, + led2: Pin, PB2>, + led3: Pin, PB1>, + led4: Pin, PD3>, } impl FourLedDisplay { pub fn new( - mut led1: Pin, PD3>, - mut led2: Pin, PB1>, - mut led3: Pin, PB2>, - mut led4: Pin, PB3>, + mut led1: Pin, PB3>, + mut led2: Pin, PB2>, + mut led3: Pin, PB1>, + mut led4: Pin, PD3>, ) -> Self { led1.enable(); led2.enable();