109 lines
2.9 KiB
Python
109 lines
2.9 KiB
Python
"""
|
|
Shared fixtures for laser_control tests.
|
|
"""
|
|
|
|
import pytest
|
|
import struct
|
|
from unittest.mock import MagicMock, patch
|
|
from laser_control.protocol import Protocol, _build_crc, _flipfour, _int_to_hex4
|
|
from laser_control.controller import LaserController
|
|
from laser_control.conversions import (
|
|
current_n_to_ma, temp_n_to_c, temp_ext_n_to_c,
|
|
voltage_3v3_n_to_v, voltage_5v_n_to_v, voltage_7v_n_to_v,
|
|
)
|
|
|
|
|
|
def make_valid_response(
|
|
current1_n: int = 10000,
|
|
current2_n: int = 12000,
|
|
temp1_n: int = 30000,
|
|
temp2_n: int = 32000,
|
|
temp_ext1_n: int = 2048,
|
|
temp_ext2_n: int = 2048,
|
|
mon_3v3_n: int = 2703, # ~3.3V
|
|
mon_5v1_n: int = 2731, # ~5.0V
|
|
mon_5v2_n: int = 2731,
|
|
mon_7v0_n: int = 1042, # ~7.0V
|
|
message_id: int = 12345,
|
|
) -> bytes:
|
|
"""
|
|
Build a syntactically valid 30-byte DATA response.
|
|
|
|
Words (each 2 bytes, little-endian via flipfour):
|
|
0 header
|
|
1 I1
|
|
2 I2
|
|
3 TO6_LSB
|
|
4 TO6_MSB
|
|
5 Temp_1
|
|
6 Temp_2
|
|
7 Temp_Ext_1
|
|
8 Temp_Ext_2
|
|
9 MON_3V3
|
|
10 MON_5V1
|
|
11 MON_5V2
|
|
12 MON_7V0
|
|
13 Message_ID
|
|
14 CRC
|
|
"""
|
|
words_raw = [
|
|
0xABCD, # Word 0 header
|
|
current1_n, # Word 1
|
|
current2_n, # Word 2
|
|
0, # Word 3 TO6_LSB
|
|
0, # Word 4 TO6_MSB
|
|
temp1_n, # Word 5
|
|
temp2_n, # Word 6
|
|
temp_ext1_n, # Word 7
|
|
temp_ext2_n, # Word 8
|
|
mon_3v3_n, # Word 9
|
|
mon_5v1_n, # Word 10
|
|
mon_5v2_n, # Word 11
|
|
mon_7v0_n, # Word 12
|
|
message_id, # Word 13
|
|
0, # Word 14 CRC placeholder
|
|
]
|
|
|
|
# Build hex string with flipfour applied
|
|
hex_str = ""
|
|
for w in words_raw:
|
|
hex_str += _flipfour(_int_to_hex4(w))
|
|
|
|
# Compute CRC over words 1..13 (indices 4..55 in hex, i.e. skip word 0)
|
|
words_hex = [hex_str[i:i+4] for i in range(0, len(hex_str), 4)]
|
|
crc_words = words_hex[1:14] # words 1..13
|
|
crc_val = int(crc_words[0], 16)
|
|
for w in crc_words[1:]:
|
|
crc_val ^= int(w, 16)
|
|
|
|
# Replace CRC word
|
|
hex_str = hex_str[:56] + _flipfour(_int_to_hex4(crc_val))
|
|
return bytes.fromhex(hex_str)
|
|
|
|
|
|
@pytest.fixture
|
|
def valid_response_bytes():
|
|
"""Pre-built valid 30-byte device response."""
|
|
return make_valid_response()
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_serial():
|
|
"""Mock serial.Serial object."""
|
|
with patch('serial.Serial') as mock_cls:
|
|
mock_instance = MagicMock()
|
|
mock_instance.is_open = True
|
|
mock_cls.return_value = mock_instance
|
|
yield mock_instance
|
|
|
|
|
|
@pytest.fixture
|
|
def connected_controller(mock_serial):
|
|
"""LaserController with mocked serial connection."""
|
|
mock_serial.read.return_value = make_valid_response()
|
|
|
|
ctrl = LaserController(port='/dev/ttyUSB0')
|
|
with patch('serial.Serial', return_value=mock_serial):
|
|
ctrl._protocol._serial = mock_serial
|
|
mock_serial.is_open = True
|
|
return ctrl |