Initial commit: aplicatie de cantarire si etichetare
Aplicatie Flask + SQLite pentru productie alimentara: cantarirea componentelor unui produs finit si tiparirea etichetei prin QZ Tray. - produse finite (retete) formate din componente cantarite - designer vizual de etichete (mm/px, zona sigura, campuri variabile, cod QR cu continut din mai multe bucati) - legare produs finit -> sablon de eticheta - navigare pe doua taburi: Cantarire / Setari - administrare: componente, produse finite, sabloane, campuri, istoric - backup, resetare baza de date, checklist de pregatire, /healthz - CLI de administrare si serviciu systemd pentru productie - vendor/syncpulse-scale-bridge (GPL-3.0-or-later) pentru citirea cantarului
This commit is contained in:
+112
@@ -0,0 +1,112 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""Auto-detection against simulated scales that only understand their own settings."""
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
from scale_bridge.detect import Detector, Timings, readability
|
||||
from scale_bridge.simulator import SimulatorBank
|
||||
|
||||
FAST = Timings(passive_s=0.5, probe_s=0.15, confirm_s=0.4, drain_s=0.02)
|
||||
|
||||
|
||||
class Silent:
|
||||
"""A port with nothing connected."""
|
||||
in_waiting = 0
|
||||
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
|
||||
def read(self, n=1):
|
||||
time.sleep(0.01)
|
||||
return b""
|
||||
|
||||
def write(self, data):
|
||||
return len(data)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
||||
class Chatter(Silent):
|
||||
"""Readable text without any weight in it."""
|
||||
|
||||
def read(self, n=1):
|
||||
time.sleep(0.01)
|
||||
return b"HELLO WORLD\r\n" if self.settings.baudrate == 9600 else b""
|
||||
|
||||
@property
|
||||
def in_waiting(self):
|
||||
return 0
|
||||
|
||||
|
||||
def detect(spec, port="COM90", thorough=False):
|
||||
bank = SimulatorBank(spec)
|
||||
events = []
|
||||
result = Detector(bank.opener(), log=lambda code, **kw: events.append(code), thorough=thorough,
|
||||
timings=FAST).run_port(port)
|
||||
return result, events
|
||||
|
||||
|
||||
@pytest.mark.parametrize("spec,protocol,baud,framing,mode", [
|
||||
("mahak_mds", "mahak_mds", 9600, "8N1", "poll"),
|
||||
("toledo_cont:4800:7E1", "toledo_cont", 4800, "7E1", "continuous"),
|
||||
("xk3190_tf0:2400", "xk3190_tf0", 2400, "8N1", "continuous"),
|
||||
("xk3190_reversed:1200", "xk3190_reversed", 1200, "8N1", "continuous"),
|
||||
("mt_sics", "mt_sics", 9600, "8N1", "poll"),
|
||||
("and_std:19200", "and_std", 19200, "8N1", "poll"),
|
||||
("sma:9600:7E1", "sma", 9600, "7E1", "poll"),
|
||||
("sartorius:1200:7E1", "sartorius", 1200, "7E1", "poll"),
|
||||
("cas_enq", "cas_enq", 9600, "8N1", "poll"),
|
||||
])
|
||||
def test_finds_protocol_speed_and_framing(spec, protocol, baud, framing, mode):
|
||||
result, events = detect(spec)
|
||||
assert result["found"], events
|
||||
assert result["protocol"] == protocol
|
||||
assert result["serial"]["baudrate"] == baud
|
||||
s = result["serial"]
|
||||
assert f"{s['bytesize']}{s['parity']}{s['stopbits']}" == framing
|
||||
assert result["mode"] == mode
|
||||
assert 0 < result["confidence"] <= 0.99
|
||||
assert events[0] == "port_start" and "found" in events
|
||||
|
||||
|
||||
def test_thorough_search_reaches_7o1():
|
||||
result, _ = detect("ohaus:9600:7O1", thorough=True)
|
||||
assert result["found"] and result["protocol"] == "ohaus"
|
||||
assert result["serial"]["parity"] == "O"
|
||||
|
||||
|
||||
def test_nothing_connected():
|
||||
detector = Detector(lambda s: Silent(s), timings=FAST)
|
||||
result = detector.run_port("COM5")
|
||||
assert result["found"] is False and result["unknown"] is None
|
||||
|
||||
|
||||
def test_unknown_readable_data_is_reported():
|
||||
detector = Detector(lambda s: Chatter(s), timings=FAST)
|
||||
result = detector.run_port("COM5")
|
||||
assert result["found"] is False
|
||||
assert result["unknown"]["baud"] == 9600
|
||||
assert "HELLO" in result["unknown"]["sample_text"]
|
||||
|
||||
|
||||
def test_cancel_stops_quickly():
|
||||
detector = Detector(lambda s: Silent(s), cancelled=lambda: True, timings=FAST)
|
||||
started = time.monotonic()
|
||||
result = detector.run_port("COM5")
|
||||
assert time.monotonic() - started < 0.5
|
||||
assert result["found"] is False and result["cancelled"] is True
|
||||
|
||||
|
||||
def test_open_failure_is_reported():
|
||||
def refuse(settings):
|
||||
raise OSError("Access is denied")
|
||||
result = Detector(refuse, timings=FAST).run_port("COM5")
|
||||
assert result["found"] is False and "Access is denied" in result["error"]
|
||||
|
||||
|
||||
def test_readability():
|
||||
assert readability(b"ST,+0.55 kg\r\n") == 1.0
|
||||
assert readability(bytes([0xD3, 0xD4])) == 0.0
|
||||
assert readability(bytes([0xD3, 0xD4]), mask7=True) == 1.0
|
||||
Reference in New Issue
Block a user