Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
+241
View File
@@ -0,0 +1,241 @@
import os
import tempfile
import time
import unittest
from unittest.mock import Mock, patch
from app import create_app, db
from app.services.hardware import ScalesReader
from app.services.hardware.hx711_wrapper import HX711UnavailableError
from config import TestingConfig
class ScalesReaderConfig(TestingConfig):
_TMP_DIR = tempfile.mkdtemp(prefix="wesp-scales-reader-tests-")
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP_DIR, 'recipes_test.db')}"
SQLALCHEMY_BINDS = {"reports": f"sqlite:///{os.path.join(_TMP_DIR, 'reports_test.db')}"}
SIMULATION_MODE = True
READ_INTERVAL = 0.01
class ScalesReaderTests(unittest.TestCase):
def setUp(self) -> None:
self.app = create_app(ScalesReaderConfig)
self.ctx = self.app.app_context()
self.ctx.push()
db.create_all()
def tearDown(self) -> None:
db.session.remove()
db.drop_all()
self.ctx.pop()
def test_reader_start_stop_and_weight_pipeline(self) -> None:
reader = ScalesReader(
simulation_mode=True,
read_interval=0.01,
samples_per_read=2,
sample_history_size=50,
median_window=4,
avg_window=3,
weights=(0.2, 0.3, 0.5),
smoothing_factor=0.3,
round_to_step=1.0,
tare_raw_window=2,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader.start()
time.sleep(0.08)
w1 = reader.get_current_weight()
self.assertIsInstance(w1, int)
self.assertGreaterEqual(w1, 0)
tare_val = reader.tare()
self.assertIsInstance(tare_val, float)
time.sleep(0.05)
w2 = reader.get_current_weight()
self.assertGreaterEqual(w2, 0)
applied = reader.calibrate(1.25)
self.assertEqual(applied, 1.25)
self.assertEqual(reader.get_counts_per_kg(), 1.25)
with self.assertRaises(ValueError):
reader.calibrate(0)
reader.stop()
def test_negative_weight_not_clamped_to_zero(self) -> None:
reader = ScalesReader(
simulation_mode=False,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=1,
avg_window=1,
weights=(1.0,),
smoothing_factor=1.0,
round_to_step=1.0,
tare_raw_window=1,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader._counts_per_kg = 1.0
reader._tare_raw = 0.0
reader._scale_hardware_platform = True
mock_hx = Mock()
mock_hx._device = object()
mock_hx.read_weight_sample.return_value = -100.0
reader._hx711 = mock_hx
reader.start()
time.sleep(0.12)
self.assertLess(reader.get_current_weight(), 0)
reader.stop()
def test_real_hardware_mode_inits_hx711_driver(self) -> None:
reader = ScalesReader(
simulation_mode=False,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=1,
avg_window=1,
weights=(1.0,),
smoothing_factor=1.0,
round_to_step=1.0,
tare_raw_window=1,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader._scale_hardware_platform = True
device = Mock()
device.get_raw_data_mean.return_value = 50000.0
hx_mod = Mock()
hx_mod.HX711.return_value = device
with patch.dict("sys.modules", {"hx711": hx_mod}):
reader._sync_hx711_wrapper_mode()
self.assertFalse(reader._hx711.simulation_mode)
self.assertIs(reader._hx711._device, device)
reader._counts_per_kg = 1000.0
reader._tare_raw = 0.0
reader.start()
time.sleep(0.12)
self.assertGreater(reader.get_current_weight(), 0)
reader.stop()
def test_non_simulation_does_not_invent_weight_when_hx711_missing(self) -> None:
reader = ScalesReader(
simulation_mode=False,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=3,
avg_window=2,
weights=(0.2, 0.3, 0.5),
smoothing_factor=0.3,
round_to_step=1.0,
tare_raw_window=2,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader._scale_hardware_platform = True
mock_hx = Mock()
mock_hx._device = None
mock_hx.simulation_mode = False
mock_hx.read_weight_sample.side_effect = HX711UnavailableError("нет датчика")
reader._hx711 = mock_hx
reader.start()
time.sleep(0.08)
self.assertEqual(reader.get_current_weight(), 0)
health = reader.get_scale_health()
self.assertFalse(health["hx711_ok"])
self.assertIsNotNone(health["hx711_error"])
reader.stop()
def test_non_arm_skips_hx711_poll_and_logs(self) -> None:
from unittest.mock import patch
reader = ScalesReader(
simulation_mode=False,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=1,
avg_window=1,
weights=(1.0,),
smoothing_factor=1.0,
round_to_step=1.0,
tare_raw_window=1,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader._scale_hardware_platform = False
mock_hx = Mock()
mock_hx.read_weight_sample.side_effect = HX711UnavailableError("не должен вызываться")
reader._hx711 = mock_hx
reader.start()
time.sleep(0.08)
mock_hx.read_weight_sample.assert_not_called()
health = reader.get_scale_health()
self.assertTrue(health.get("hx711_skipped"))
self.assertIsNone(health.get("hx711_error"))
reader.stop()
def test_simulation_toggle_and_weight_adjust(self) -> None:
reader = ScalesReader(
simulation_mode=False,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=1,
avg_window=1,
weights=(1.0,),
smoothing_factor=1.0,
round_to_step=1.0,
tare_raw_window=1,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
reader.start()
state = reader.set_simulation_mode(True)
self.assertTrue(state["simulation_mode"])
w = reader.adjust_simulation_weight(5)
self.assertEqual(w, 5)
self.assertEqual(reader.get_current_weight(), 5)
w2 = reader.adjust_simulation_weight(-2)
self.assertEqual(w2, 3)
reader.set_simulation_mode(False)
off = reader.get_simulation_state()
self.assertFalse(off["simulation_mode"])
with self.assertRaises(ValueError):
reader.adjust_simulation_weight(1)
with self.assertRaises(ValueError):
reader.set_simulation_weight(10)
reader.stop()
def test_set_simulation_weight_absolute(self) -> None:
reader = ScalesReader(
simulation_mode=True,
read_interval=0.01,
samples_per_read=1,
sample_history_size=20,
median_window=1,
avg_window=1,
weights=(1.0,),
smoothing_factor=1.0,
round_to_step=1.0,
tare_raw_window=1,
hx711_dout_pin=2,
hx711_pd_sck_pin=3,
)
w = reader.set_simulation_weight(42)
self.assertEqual(w, 42)
reader.start()
time.sleep(0.05)
self.assertEqual(reader.get_current_weight(), 42)
reader.stop()
if __name__ == "__main__":
unittest.main()