Skip to content

Commit 429a4d8

Browse files
Merge pull request #6 from generalmattza/main
daily uodates
2 parents b2c6037 + 695934f commit 429a4d8

File tree

5 files changed

+115
-12
lines changed

5 files changed

+115
-12
lines changed

src/app_monitor/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.1.0"
1+
__version__ = "0.1.4"
22

33

44
from .app_monitor import TerminalManager, SocketManager

src/app_monitor/app_monitor.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import asyncio
22
from copy import deepcopy
33
import sys
4+
import asyncio
5+
import json
6+
from flask_socketio import SocketIO
47

58
from app_monitor.elements_base import (
69
ProgressBar,
7-
Table,
810
TextElement,
911
RangeBar,
1012
MonitorGroup,
@@ -105,11 +107,6 @@ async def update_fixed_rate(self, frequency=30):
105107
)
106108

107109

108-
import asyncio
109-
import json
110-
from flask_socketio import SocketIO
111-
112-
113110
class SocketManager(MonitorManager):
114111
"""Subclass of MonitorManager that adds functionality to push data to a WebSocket."""
115112

src/app_monitor/elements_advanced.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1+
from dataclasses import asdict, dataclass
2+
from typing import Mapping
13
from app_monitor.elements_base import MonitorElement, ProgressBar, Table, TextElement
4+
from app_monitor.text_formatter import TextFormat
5+
6+
7+
class UnpackMixin(Mapping):
8+
def __iter__(self):
9+
return iter(asdict(self).keys())
10+
11+
def __len__(self):
12+
return len(asdict(self))
13+
14+
def __getitem__(self, key):
15+
if key not in asdict(self):
16+
raise KeyError(f"Key {key} not found in {self.__class__.__name__}")
17+
return getattr(self, key)
218

319

420
class CoordinateTextElement(TextElement):
@@ -22,6 +38,60 @@ def update(self, x=None, y=None, z=None, units=None):
2238
)
2339

2440

41+
class ScaledTextElement(TextElement):
42+
def __init__(
43+
self, element_id, units="", static_text=None, scale=1, text_format=None
44+
):
45+
super().__init__(
46+
element_id=element_id,
47+
text="",
48+
static_text=static_text,
49+
text_format=text_format,
50+
)
51+
self.scale = scale
52+
self.units = units
53+
54+
def update(self, text):
55+
scaled_value = float(text) * self.scale
56+
return super().update(scaled_value)
57+
58+
59+
@dataclass
60+
class TextElementSettings(UnpackMixin):
61+
element_id: str
62+
text_format: TextFormat = None
63+
static_text: str = ""
64+
text: str = ""
65+
width: int = None
66+
_factory: TextElement = TextElement
67+
68+
def build(self):
69+
return self._factory(
70+
element_id=self.element_id,
71+
text=self.text,
72+
static_text=self.static_text,
73+
text_format=self.text_format,
74+
width=self.width,
75+
)
76+
77+
78+
@dataclass
79+
class ScaledTextElementSettings(TextElementSettings):
80+
scale: float = 1
81+
units: str = ""
82+
83+
_factory: ScaledTextElement = ScaledTextElement
84+
85+
def build(self):
86+
return self._factory(
87+
element_id=self.element_id,
88+
units=self.units,
89+
static_text=self.static_text,
90+
scale=self.scale,
91+
text_format=self.text_format,
92+
)
93+
94+
2595
# Machine state class
2696
class MachineState(MonitorElement):
2797
"""Class for rendering machine states using binary values."""

src/app_monitor/elements_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def __init__(self, element_id=None, border=False, width=MAX_MONITOR_WIDTH):
3434
"""
3535
self.element_id = element_id or self.get_unique_id()
3636
self.border = border
37-
self.width = width
37+
self.width = MAX_MONITOR_WIDTH if width is None else width
3838

3939
def display(self):
4040
"""Render the monitor element for display."""

src/app_monitor/server.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import zmq
44
import zmq.asyncio
55
import serial
6-
6+
import struct
7+
from collections import OrderedDict
78
from .logger import logger
89

910

@@ -64,6 +65,7 @@ def __init__(
6465
port="/dev/ttyUSB0",
6566
baudrate=9600,
6667
decoder=None,
68+
validator=None,
6769
):
6870
super().__init__(monitor_manager)
6971
if serial_instance:
@@ -76,6 +78,7 @@ def __init__(
7678
self.port = self.serial_connection.port
7779
self.baudrate = self.serial_connection.baudrate
7880
self.decoder = decoder
81+
self.validator = validator
7982

8083
def detect_devices(
8184
self,
@@ -115,9 +118,12 @@ async def start(self, frequency: float = 30):
115118
if self.serial_connection.in_waiting:
116119
# Read available data on the serial port
117120
if data := self.serial_connection.readline():
118-
if self.decoder:
121+
if self.validator:
122+
data = self.validator.validate(data)
123+
if self.decoder and data:
119124
data = self.decoder.decode(data)
120-
self.process_update(data)
125+
if data:
126+
self.process_update(data)
121127
await asyncio.sleep(1 / frequency)
122128

123129
except Exception as e:
@@ -151,4 +157,34 @@ def __init__(self, keys, separator=","):
151157

152158
def decode(self, packet):
153159
data = packet.decode("utf-8").strip().split(self.separator)
154-
return dict(zip(self.keys, data))
160+
return OrderedDict(zip(self.keys, data))
161+
162+
163+
class StructDecoder(Decoder):
164+
def __init__(self, data_keys, packet_format=None):
165+
self.packet_format = packet_format
166+
self.data_keys = data_keys
167+
168+
def decode(self, packet):
169+
if self.packet_format:
170+
packet = struct.unpack(self.packet_format, packet)
171+
if self.data_keys:
172+
packet = OrderedDict(zip(self.data_keys, packet))
173+
return packet
174+
175+
176+
class Validator:
177+
@abstractmethod
178+
def validate(self, packet): ...
179+
180+
class WindowValidator(Validator):
181+
def __init__(self, window_size=10, start_byte=0xA5, end_byte=0x5A):
182+
self.window_size = window_size
183+
self.start_byte = start_byte
184+
self.end_byte = end_byte
185+
186+
def validate(self, packet):
187+
if len(packet) == self.window_size and packet[0] == self.start_byte and packet[-1] == self.end_byte:
188+
# Return packet without start and end bytes
189+
return packet[1:-1]
190+
return False

0 commit comments

Comments
 (0)