feat: DG430 V2.0.3 — 波动测试模式支持
- dg430.py: 新增 DG430WaveStatus + parse_b4_wave_status() 0xB4解析 - dg430.py: 0x4C 扩展6字段(向后兼容旧版长度) - models.py: tb_fixture_param DDL + upsert 新增6个波动参数 - handlers.py: parse_loop 添加0xB4处理; 0x4C传参扩展 - TestMode=1 模拟过车→波动测试 (注释)
This commit is contained in:
98
src/dg430.py
98
src/dg430.py
@@ -19,7 +19,7 @@ class DG430Status:
|
|||||||
"""解析后的 DG430 状态数据"""
|
"""解析后的 DG430 状态数据"""
|
||||||
addr: int # 地址
|
addr: int # 地址
|
||||||
dev_model: int # 1 PD132, 2 DLD110
|
dev_model: int # 1 PD132, 2 DLD110
|
||||||
test_mode: int # 0 灵敏度, 1 模拟过车
|
test_mode: int # 0 灵敏度, 1 波动测试
|
||||||
is_finished: bool # 是否正常完成
|
is_finished: bool # 是否正常完成
|
||||||
finish_code: int # 0 正常, 1 未完成, 2 地感死机
|
finish_code: int # 0 正常, 1 未完成, 2 地感死机
|
||||||
fault: int # bitmask
|
fault: int # bitmask
|
||||||
@@ -150,7 +150,7 @@ def parse_b2_status(data: bytes) -> DG430Status | None:
|
|||||||
|
|
||||||
# 设备型号
|
# 设备型号
|
||||||
dev_model = payload[0] # 1=PD132, 2=DLD110
|
dev_model = payload[0] # 1=PD132, 2=DLD110
|
||||||
test_mode = payload[1] # 0=灵敏度, 1=模拟过车
|
test_mode = payload[1] # 0=灵敏度, 1=波动测试
|
||||||
finish_code = payload[2] # 0=正常, 1=未完成, 2=死机
|
finish_code = payload[2] # 0=正常, 1=未完成, 2=死机
|
||||||
fault = payload[3] # bitmask
|
fault = payload[3] # bitmask
|
||||||
relay_out = payload[4] # bitmask
|
relay_out = payload[4] # bitmask
|
||||||
@@ -191,6 +191,70 @@ def parse_b2_status(data: bytes) -> DG430Status | None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ─── 0xB4 波动测试上报 ──────────────────────────────────────────
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DG430WaveStatus:
|
||||||
|
"""波动测试状态上报数据"""
|
||||||
|
addr: int # 地址
|
||||||
|
remain_count: int # 剩余波动次数
|
||||||
|
relay_out: int # 继电器输出 bitmask
|
||||||
|
work_freq: float # 工作频率 Hz
|
||||||
|
curr_dist: int # 当前距离 mm
|
||||||
|
speed: int # 当前速度 dm/s
|
||||||
|
near_dist: int # 波动最近距离 mm
|
||||||
|
far_dist: int # 波动最远距离 mm
|
||||||
|
enter_dist: int # 进入高度 mm
|
||||||
|
leave_dist: int # 离开高度 mm
|
||||||
|
|
||||||
|
|
||||||
|
def parse_b4_wave_status(data: bytes) -> DG430WaveStatus | None:
|
||||||
|
"""解析 0xB4 波动测试状态上报包
|
||||||
|
|
||||||
|
格式: STX | ADDR | 11 | B4 | DATA(16B) | XOR | SUM
|
||||||
|
DATA: RemainCount(1) | Relay(1) | WorkFreq(2 LE) | CurrDist(2 LE) |
|
||||||
|
Speed(2 LE) | NearDist(2 LE) | FarDist(2 LE) |
|
||||||
|
EnterDist(2 LE) | LeaveDist(2 LE)
|
||||||
|
"""
|
||||||
|
if not verify_packet(data):
|
||||||
|
logger.warning("DG430 B4 数据包校验失败")
|
||||||
|
return None
|
||||||
|
|
||||||
|
cmd = data[3]
|
||||||
|
if cmd != 0xB4:
|
||||||
|
logger.debug(f"非 B4 指令: 0x{cmd:02X}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
payload = data[4:3 + data[2]]
|
||||||
|
if len(payload) < 16:
|
||||||
|
logger.warning(f"B4 数据长度不足: {len(payload)} < 16")
|
||||||
|
return None
|
||||||
|
|
||||||
|
addr = data[1] & 0x7F
|
||||||
|
remain_count = payload[0]
|
||||||
|
relay_out = payload[1]
|
||||||
|
work_freq = _le16(payload, 2) * 10.0
|
||||||
|
curr_dist = _le16(payload, 4)
|
||||||
|
speed = _le16(payload, 6)
|
||||||
|
near_dist = _le16(payload, 8)
|
||||||
|
far_dist = _le16(payload, 10)
|
||||||
|
enter_dist = _le16(payload, 12)
|
||||||
|
leave_dist = _le16(payload, 14)
|
||||||
|
|
||||||
|
return DG430WaveStatus(
|
||||||
|
addr=addr,
|
||||||
|
remain_count=remain_count,
|
||||||
|
relay_out=relay_out,
|
||||||
|
work_freq=round(work_freq, 1),
|
||||||
|
curr_dist=curr_dist,
|
||||||
|
speed=speed,
|
||||||
|
near_dist=near_dist,
|
||||||
|
far_dist=far_dist,
|
||||||
|
enter_dist=enter_dist,
|
||||||
|
leave_dist=leave_dist,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ─── 故障解码 ───────────────────────────────────────────────────────
|
# ─── 故障解码 ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
FAULT_BITS = {
|
FAULT_BITS = {
|
||||||
@@ -290,7 +354,7 @@ class DG430FixtureParams:
|
|||||||
flag: int # 0=正常, 1=故障
|
flag: int # 0=正常, 1=故障
|
||||||
dev_addr: int # 设备地址
|
dev_addr: int # 设备地址
|
||||||
dev_type: int # 设备型号
|
dev_type: int # 设备型号
|
||||||
test_mode: int # 0 灵敏度, 1 模拟过车
|
test_mode: int # 0 灵敏度, 1 波动测试
|
||||||
reset_dis: int # 复位距离 cm
|
reset_dis: int # 复位距离 cm
|
||||||
minus_dis: int # 皮距 cm
|
minus_dis: int # 皮距 cm
|
||||||
sens_min: int # 灵敏度最小值
|
sens_min: int # 灵敏度最小值
|
||||||
@@ -299,14 +363,22 @@ class DG430FixtureParams:
|
|||||||
fre_max: int # 频率最大值 Hz
|
fre_max: int # 频率最大值 Hz
|
||||||
peak_min: int # 峰峰值最小值
|
peak_min: int # 峰峰值最小值
|
||||||
peak_max: int # 峰峰值最大值
|
peak_max: int # 峰峰值最大值
|
||||||
|
far_tol: int # 最远容差 cm
|
||||||
|
near_tol: int # 最近容差 cm
|
||||||
|
step_tol: int # 步进容差 cm
|
||||||
|
back_forth: int # 来回次数
|
||||||
|
near_stay: int # 最近停留时间 ms
|
||||||
|
far_stay: int # 最远停留时间 ms
|
||||||
|
|
||||||
|
|
||||||
def parse_4c_params(data: bytes) -> DG430FixtureParams | None:
|
def parse_4c_params(data: bytes) -> DG430FixtureParams | None:
|
||||||
"""解析 0x4C 查询测试参数响应
|
"""解析 0x4C 查询测试参数响应 (V2.0.3 扩展)
|
||||||
|
|
||||||
格式: 7F | ADDR | 13 | 4C | Flag | Addr | DevType | TestMode |
|
格式: 7F | ADDR | 1B | 4C | Flag | Addr | DevType | TestMode |
|
||||||
ResetDis | MinusDis | SensMin(2) | SensMax(2) |
|
ResetDis | MinusDis | SensMin(2) | SensMax(2) |
|
||||||
FreMin(2) | FreMax(2) | PeakMin(2) | PeakMax(2) | XOR | SUM
|
FreMin(2) | FreMax(2) | PeakMin(2) | PeakMax(2) |
|
||||||
|
FarTol(1) | NearTol(1) | StepTol(1) | BackForth(1) |
|
||||||
|
NearStay(2) | FarStay(2) | XOR | SUM
|
||||||
"""
|
"""
|
||||||
if not verify_packet(data):
|
if not verify_packet(data):
|
||||||
return None
|
return None
|
||||||
@@ -320,6 +392,14 @@ def parse_4c_params(data: bytes) -> DG430FixtureParams | None:
|
|||||||
|
|
||||||
addr = data[1] & 0x7F
|
addr = data[1] & 0x7F
|
||||||
# 0x4B/0x4C 多字节字段为小端序
|
# 0x4B/0x4C 多字节字段为小端序
|
||||||
|
# V2.0.3 新增6个波动参数字段,兼容旧版(长度不足时默认为0)
|
||||||
|
far_tol = payload[18] if len(payload) >= 19 else 0
|
||||||
|
near_tol = payload[19] if len(payload) >= 20 else 0
|
||||||
|
step_tol = payload[20] if len(payload) >= 21 else 0
|
||||||
|
back_forth = payload[21] if len(payload) >= 22 else 0
|
||||||
|
near_stay = _le16(payload, 22) if len(payload) >= 24 else 0
|
||||||
|
far_stay = _le16(payload, 24) if len(payload) >= 26 else 0
|
||||||
|
|
||||||
return DG430FixtureParams(
|
return DG430FixtureParams(
|
||||||
addr=addr,
|
addr=addr,
|
||||||
flag=payload[0],
|
flag=payload[0],
|
||||||
@@ -334,6 +414,12 @@ def parse_4c_params(data: bytes) -> DG430FixtureParams | None:
|
|||||||
fre_max=_le16(payload, 12),
|
fre_max=_le16(payload, 12),
|
||||||
peak_min=_le16(payload, 14),
|
peak_min=_le16(payload, 14),
|
||||||
peak_max=_le16(payload, 16),
|
peak_max=_le16(payload, 16),
|
||||||
|
far_tol=far_tol,
|
||||||
|
near_tol=near_tol,
|
||||||
|
step_tol=step_tol,
|
||||||
|
back_forth=back_forth,
|
||||||
|
near_stay=near_stay,
|
||||||
|
far_stay=far_stay,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ from src.dg430 import (
|
|||||||
parse_4a_version,
|
parse_4a_version,
|
||||||
parse_flag_response,
|
parse_flag_response,
|
||||||
parse_4c_params,
|
parse_4c_params,
|
||||||
|
parse_b4_wave_status,
|
||||||
get_packet_cmd,
|
get_packet_cmd,
|
||||||
hex_str_to_bytes,
|
hex_str_to_bytes,
|
||||||
split_packets,
|
split_packets,
|
||||||
@@ -322,6 +323,12 @@ async def parse_loop():
|
|||||||
FreMax=params.fre_max,
|
FreMax=params.fre_max,
|
||||||
PeakMin=params.peak_min,
|
PeakMin=params.peak_min,
|
||||||
PeakMax=params.peak_max,
|
PeakMax=params.peak_max,
|
||||||
|
FarTol=params.far_tol,
|
||||||
|
NearTol=params.near_tol,
|
||||||
|
StepTol=params.step_tol,
|
||||||
|
BackForth=params.back_forth,
|
||||||
|
NearStay=params.near_stay,
|
||||||
|
FarStay=params.far_stay,
|
||||||
)
|
)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"0x4C 工装参数已更新 dnt_id={dnt_id} "
|
f"0x4C 工装参数已更新 dnt_id={dnt_id} "
|
||||||
@@ -332,6 +339,28 @@ async def parse_loop():
|
|||||||
has_valid = True
|
has_valid = True
|
||||||
all_failed = False
|
all_failed = False
|
||||||
|
|
||||||
|
# ── 0xB4 波动测试上报 ──
|
||||||
|
elif cmd == 0xB4:
|
||||||
|
if not verify_packet(pkt):
|
||||||
|
logger.debug(f"0xB4 数据包校验失败: {device_id}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
wave = parse_b4_wave_status(pkt)
|
||||||
|
if wave is None:
|
||||||
|
logger.warning(f"0xB4 解析失败: {device_id}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
relay_info = decode_relay_info(wave.relay_out)
|
||||||
|
logger.info(
|
||||||
|
f"B4波动上报: {device_id} 剩余={wave.remain_count} "
|
||||||
|
f"当前距离={wave.curr_dist}mm 速度={wave.speed}dm/s "
|
||||||
|
f"最近={wave.near_dist}mm 最远={wave.far_dist}mm "
|
||||||
|
f"进入={wave.enter_dist}mm 离开={wave.leave_dist}mm "
|
||||||
|
f"继电器={relay_info}"
|
||||||
|
)
|
||||||
|
has_valid = True
|
||||||
|
all_failed = False
|
||||||
|
|
||||||
# ── 测试指令 Flag 响应(不匹配 serialnet,等待 B2 完成)──
|
# ── 测试指令 Flag 响应(不匹配 serialnet,等待 B2 完成)──
|
||||||
elif cmd in (0xB0, 0xB1, 0xBA, 0xBB, 0xBC):
|
elif cmd in (0xB0, 0xB1, 0xBA, 0xBB, 0xBC):
|
||||||
if not verify_packet(pkt):
|
if not verify_packet(pkt):
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ async def _create_tables(pool: aiomysql.Pool):
|
|||||||
`dnt_id` INT NOT NULL COMMENT 'FK → dnt_info.id',
|
`dnt_id` INT NOT NULL COMMENT 'FK → dnt_info.id',
|
||||||
`Addr` TINYINT DEFAULT 1 COMMENT '工装设备地址',
|
`Addr` TINYINT DEFAULT 1 COMMENT '工装设备地址',
|
||||||
`DevType` TINYINT DEFAULT 0 COMMENT '被检设备型号类型编码',
|
`DevType` TINYINT DEFAULT 0 COMMENT '被检设备型号类型编码',
|
||||||
`TestMode` TINYINT DEFAULT 0 COMMENT '0 灵敏度测试, 1 模拟过车',
|
`TestMode` TINYINT DEFAULT 0 COMMENT '0 灵敏度测试, 1 波动测试',
|
||||||
`RestDis` INT DEFAULT 0 COMMENT '复位距离 cm',
|
`RestDis` INT DEFAULT 0 COMMENT '复位距离 cm',
|
||||||
`MinusDis` INT DEFAULT 0 COMMENT '皮距/开始距离 cm',
|
`MinusDis` INT DEFAULT 0 COMMENT '皮距/开始距离 cm',
|
||||||
`SensMin` INT DEFAULT 0 COMMENT '灵敏度最小值',
|
`SensMin` INT DEFAULT 0 COMMENT '灵敏度最小值',
|
||||||
@@ -163,6 +163,12 @@ async def _create_tables(pool: aiomysql.Pool):
|
|||||||
`FreMax` INT DEFAULT 0 COMMENT '频率最大值 Hz',
|
`FreMax` INT DEFAULT 0 COMMENT '频率最大值 Hz',
|
||||||
`PeakMin` INT DEFAULT 0 COMMENT '峰峰值最小值',
|
`PeakMin` INT DEFAULT 0 COMMENT '峰峰值最小值',
|
||||||
`PeakMax` INT DEFAULT 0 COMMENT '峰峰值最大值',
|
`PeakMax` INT DEFAULT 0 COMMENT '峰峰值最大值',
|
||||||
|
`FarTol` INT DEFAULT 0 COMMENT '最远容差 cm (V2.0.3)',
|
||||||
|
`NearTol` INT DEFAULT 0 COMMENT '最近容差 cm (V2.0.3)',
|
||||||
|
`StepTol` INT DEFAULT 0 COMMENT '步进容差 cm (V2.0.3)',
|
||||||
|
`BackForth` INT DEFAULT 0 COMMENT '来回次数 (V2.0.3)',
|
||||||
|
`NearStay` INT DEFAULT 0 COMMENT '最近停留时间 ms (V2.0.3)',
|
||||||
|
`FarStay` INT DEFAULT 0 COMMENT '最远停留时间 ms (V2.0.3)',
|
||||||
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
UNIQUE INDEX `idx_dnt_id` (`dnt_id`)
|
UNIQUE INDEX `idx_dnt_id` (`dnt_id`)
|
||||||
@@ -479,6 +485,7 @@ async def upsert_fixture_param(dnt_id: int, **kwargs):
|
|||||||
fields = [
|
fields = [
|
||||||
"Addr", "DevType", "TestMode", "RestDis", "MinusDis",
|
"Addr", "DevType", "TestMode", "RestDis", "MinusDis",
|
||||||
"SensMin", "SensMax", "FreMin", "FreMax", "PeakMin", "PeakMax",
|
"SensMin", "SensMax", "FreMin", "FreMax", "PeakMin", "PeakMax",
|
||||||
|
"FarTol", "NearTol", "StepTol", "BackForth", "NearStay", "FarStay",
|
||||||
]
|
]
|
||||||
if existing:
|
if existing:
|
||||||
sets = ", ".join(f"`{f}`=%s" for f in fields)
|
sets = ", ".join(f"`{f}`=%s" for f in fields)
|
||||||
|
|||||||
Reference in New Issue
Block a user