feat: split net bars in 2, small fixes

This commit is contained in:
əlemi 2022-08-30 20:48:33 +02:00
parent b1a3d7b033
commit 06ed013f19
No known key found for this signature in database
GPG key ID: BBCBFE5D7244634E
4 changed files with 84 additions and 51 deletions

View file

@ -8,6 +8,8 @@ from time import sleep
import serial import serial
import psutil import psutil
BAR_MAX_HEIGHT = 255
class State: class State:
run: bool run: bool
device: str device: str
@ -36,6 +38,7 @@ class State:
await self._loop.run_in_executor(None, self.port.write, pkt) await self._loop.run_in_executor(None, self.port.write, pkt)
except serial.SerialException as e: except serial.SerialException as e:
logging.error("[!] Error operating with device: %s", str(e)) logging.error("[!] Error operating with device: %s", str(e))
await asyncio.sleep(30)
except Exception as e: except Exception as e:
logging.exception("unhandled exception") logging.exception("unhandled exception")
self.run = False self.run = False
@ -47,42 +50,50 @@ class State:
rx = 0 rx = 0
tx = 0 tx = 0
while self.run: while self.run:
cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 1, True) cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 0.1, True)
load = [ int(((x/100) **2) * 255) for x in cpu_report ] # mypy whines but percpu returns a list
net = psutil.net_io_counters(pernic=True) net = psutil.net_io_counters(pernic=True)
d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo") 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") 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 rx = d_rx
tx = d_tx tx = d_tx
async def cpu_load_leds(self): # async def cpu_load_leds(self):
while self.run: # return
cpu_report = await self._loop.run_in_executor(None, psutil.cpu_percent, 0.05, True) # while self.run:
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.05, True)
logging.info("CPU [%d|%d|%d|%d]", *load) # load = [ int(((x/100) **2) * 255) for x in cpu_report ] # mypy whines but percpu returns a list
await self.packets.put(struct.pack("BBBBBB", 1, 4, *load)) # logging.info("CPU [%d|%d|%d|%d]", *load)
# await self.packets.put(struct.pack("BBBBBB", 1, 4, *load))
async def net_traffic_leds(self): # async def net_traffic_leds(self):
rx = 0 # return
tx = 0 # rx = 0
while self.run: # tx = 0
net = psutil.net_io_counters(pernic=True) # while self.run:
d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo") # net = psutil.net_io_counters(pernic=True)
d_tx = sum(v.bytes_sent for k, v in net.items() if k != "lo") # d_rx = sum(v.bytes_recv for k, v in net.items() if k != "lo")
logging.info("NET [TX %d | %d RX]", d_tx - tx, d_rx - rx) # d_tx = sum(v.bytes_sent for k, v in net.items() if k != "lo")
await self.packets.put(struct.pack("BBBB", 2, 2, min(d_tx - tx, 255), min(d_rx - rx, 255))) # logging.info("NET [TX %d | %d RX]", d_tx - tx, d_rx - rx)
rx = d_rx # await self.packets.put(struct.pack("BBBB", 2, 2, min(d_tx - tx, 255), min(d_rx - rx, 255)))
tx = d_tx # rx = d_rx
await asyncio.sleep(0.01) # tx = d_tx
# await asyncio.sleep(0.01)
async def run_tasks(self): async def run_tasks(self):
self._loop = asyncio.get_event_loop() self._loop = asyncio.get_event_loop()
port_manager = self._loop.create_task(self.run_port_manager()) port_manager = self._loop.create_task(self.run_port_manager())
cpu_leds = self._loop.create_task(self.cpu_load_leds()) # cpu_leds = self._loop.create_task(self.cpu_load_leds())
net_leds = self._loop.create_task(self.net_traffic_leds()) # net_leds = self._loop.create_task(self.net_traffic_leds())
display = self._loop.create_task(self.display_polling()) 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 __name__ == "__main__":
if len(sys.argv) < 2: if len(sys.argv) < 2:
@ -91,7 +102,7 @@ if __name__ == "__main__":
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
state = State(sys.argv[1]) state = State(sys.argv[1], baudrate=115200)
asyncio.run(state.run_tasks()) asyncio.run(state.run_tasks())

View file

@ -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! // 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) { pub fn draw_ui(display: &mut Display, style: &DisplayStyle) {
Rectangle::new(Point::new(0, 0), Size::new(85, 64)) Rectangle::new(Point::new(0, 0), Size::new(85, 64))
.into_styled(style.border_style) .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 // 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. // 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. // On normal screens this will look worse and you should put them back.
// Rectangle::new(Point::new(87, 16), Size::new(11, 48)) Rectangle::new(Point::new(87, 16), Size::new(11, 48))
// .into_styled(style.border_style) .into_styled(style.border_style)
// .draw(display) .draw(display)
// .unwrap(); .unwrap();
Rectangle::new(Point::new(100, 0), Size::new(28, 64)) Rectangle::new(Point::new(100, 0), Size::new(28, 64))
.into_styled(style.border_style) .into_styled(style.border_style)
@ -87,20 +98,29 @@ pub enum NetDirection {
TX, RX 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 x = match direction { NetDirection::TX => 103, NetDirection::RX => 115 };
let height = byte_to_height(value, 54); let height_fine = byte_to_height(value_fine, 54);
Rectangle::new(Point::new(x as i32, 8), Size::new(10, 54 - (height-1) as u32)) 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) .into_styled(style.background_style)
.draw(display) .draw(display)
.unwrap(); .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) .into_styled(style.bar_style)
.draw(display) .draw(display)
.unwrap(); .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_ui(display, style);
draw_cpu_bar(display, 1, cpu1, 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, 3, cpu3, style);
draw_cpu_bar(display, 4, cpu4, style); draw_cpu_bar(display, 4, cpu4, style);
draw_network_bar(display, NetDirection::TX, tx, style); draw_network_bar(display, NetDirection::TX, tx, tx_wide, style);
draw_network_bar(display, NetDirection::RX, rx, style); draw_network_bar(display, NetDirection::RX, rx, rx_wide, style);
display.flush().unwrap(); display.flush().unwrap();
} }

View file

@ -20,7 +20,7 @@ mod display;
use crate::packet::PacketBuilder; use crate::packet::PacketBuilder;
use crate::utils::FourLedDisplay; 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> { pub struct DisplayStyle<'a> {
border_style: PrimitiveStyle<BinaryColor>, border_style: PrimitiveStyle<BinaryColor>,
@ -41,10 +41,10 @@ fn main() -> ! {
let mut led_tx = pins.d4.into_output(); // red let mut led_tx = pins.d4.into_output(); // red
let button = pins.d2.into_pull_up_input(); let button = pins.d2.into_pull_up_input();
let mut cpu_leds = FourLedDisplay::new( 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.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( let i2c = arduino_hal::i2c::I2c::new(
dp.TWI, pins.a4.into_pull_up_input(), pins.a5.into_pull_up_input(), 800000 dp.TWI, pins.a4.into_pull_up_input(), pins.a5.into_pull_up_input(), 800000
@ -75,6 +75,7 @@ fn main() -> ! {
// prepare display // prepare display
let interface = I2CDisplayInterface::new(i2c); let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0).into_buffered_graphics_mode(); let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0).into_buffered_graphics_mode();
let mut s = Spinner::new(91, 10);
display.init().unwrap(); display.init().unwrap();
cpu_leds.set(1, 255); cpu_leds.set(1, 255);
@ -124,13 +125,14 @@ fn main() -> ! {
} }
}, },
PacketId::ScreenDrawPacket => { 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, 1, payload[0], &style);
draw_cpu_bar(&mut display, 2, payload[1], &style); draw_cpu_bar(&mut display, 2, payload[1], &style);
draw_cpu_bar(&mut display, 3, payload[2], &style); draw_cpu_bar(&mut display, 3, payload[2], &style);
draw_cpu_bar(&mut display, 4, payload[3], &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::TX, payload[4], payload[6], &style);
draw_network_bar(&mut display, NetDirection::RX, payload[5], &style); draw_network_bar(&mut display, NetDirection::RX, payload[5], payload[7], &style);
display.flush().unwrap(); display.flush().unwrap();
} }
}, },

View file

@ -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? // TODO can I make it a generic "Pin" and use a slice?
pub struct FourLedDisplay { pub struct FourLedDisplay {
led1: Pin<PwmOutput<Timer2Pwm>, PD3>, led1: Pin<PwmOutput<Timer2Pwm>, PB3>,
led2: Pin<PwmOutput<Timer1Pwm>, PB1>, led2: Pin<PwmOutput<Timer1Pwm>, PB2>,
led3: Pin<PwmOutput<Timer1Pwm>, PB2>, led3: Pin<PwmOutput<Timer1Pwm>, PB1>,
led4: Pin<PwmOutput<Timer2Pwm>, PB3>, led4: Pin<PwmOutput<Timer2Pwm>, PD3>,
} }
impl FourLedDisplay { impl FourLedDisplay {
pub fn new( pub fn new(
mut led1: Pin<PwmOutput<Timer2Pwm>, PD3>, mut led1: Pin<PwmOutput<Timer2Pwm>, PB3>,
mut led2: Pin<PwmOutput<Timer1Pwm>, PB1>, mut led2: Pin<PwmOutput<Timer1Pwm>, PB2>,
mut led3: Pin<PwmOutput<Timer1Pwm>, PB2>, mut led3: Pin<PwmOutput<Timer1Pwm>, PB1>,
mut led4: Pin<PwmOutput<Timer2Pwm>, PB3>, mut led4: Pin<PwmOutput<Timer2Pwm>, PD3>,
) -> Self { ) -> Self {
led1.enable(); led1.enable();
led2.enable(); led2.enable();