feat(api): 添加OLT端口管理和设备发现功能

- 在check.py中更新discover_olt方法,使用scan_and_discover替代check_olt_devices
- 在olt.py中添加get_olt_ports和toggle_olt_port接口,支持获取和控制OLT端口状态
- 添加TogglePortRequest模型用于端口操作请求验证
- 更新SSHService类,新增get_olt_ports和toggle_olt_port方法
- 优化CheckService中的MAC地址索引逻辑,支持模型信息更新
```
This commit is contained in:
2026-04-04 22:13:22 +08:00
parent 381ea7085d
commit dfa8fa62a8
21 changed files with 4121 additions and 733 deletions
+26 -20
View File
@@ -39,17 +39,18 @@ class CheckService:
online_count = 0
offline_count = 0
# 全局 MAC → id 索引,只取需要的字段
# 全局 MAC → (id, model) 索引
existing = {
row.mac_address.lower(): row.id
for row in self.db.query(ONUDevice.mac_address, ONUDevice.id).all()
row.mac_address.lower(): (row.id, row.model)
for row in self.db.query(ONUDevice.mac_address, ONUDevice.id, ONUDevice.model).all()
}
for mac, onu_info in onu_info_dict.items():
onu_id = existing.get(mac)
if onu_id is None:
entry = existing.get(mac)
if entry is None:
continue # 不在库中,跳过
onu_id, onu_model = entry
status = onu_info.status
distance_m = parse_distance(onu_info.distance_str)
if status == 'online':
@@ -57,6 +58,9 @@ class CheckService:
else:
offline_count += 1
if onu_info.model and not onu_model:
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update({"model": onu_info.model})
self.db.add(DeviceStatusHistory(
onu_device_id=onu_id,
status=status,
@@ -88,32 +92,30 @@ class CheckService:
raise Exception("关联的 OLT 不存在")
mac = device.mac_address.lower()
base_cmd = olt.slot_command # e.g. "display onu slot"
if device.slot_number is not None:
cmd = f"{base_cmd} {device.slot_number} | include {mac}"
else:
cmd = f"{base_cmd} | include {mac}"
cmd = f"{olt.slot_command} | include {mac}"
ssh = SSHService(olt.ip_address, olt.username, olt.password)
try:
ssh.connect()
output = ssh.execute_command(cmd)
# 从输出中找到包含该 MAC 的行并解析
# 跳过命令回显行(含 MAC 但无端口标识),只接受有 port_id 的行
info = None
for line in output.splitlines():
if mac in line.lower():
info = ssh._parse_device_line(line, device.slot_number)
if info:
parsed = ssh._parse_device_line(line, device.slot_number)
if parsed and parsed.port_id:
info = parsed
break
if info is None:
# 未找到该 MAC,视为离线
status = 'offline'
distance_m = None
else:
status = info.status
distance_m = parse_distance(info.distance_str)
if info.model and not device.model:
device.model = info.model
self.db.add(DeviceStatusHistory(
onu_device_id=device.id,
@@ -123,7 +125,7 @@ class CheckService:
response_data=None,
))
self.db.commit()
return {"status": status, "distance_m": distance_m}
return {"status": status, "distance_m": distance_m, "model": device.model}
finally:
ssh.close()
@@ -147,14 +149,14 @@ class CheckService:
new_count = 0
existing = {
row.mac_address.lower(): row.id
for row in self.db.query(ONUDevice.mac_address, ONUDevice.id).all()
row.mac_address.lower(): (row.id, row.model)
for row in self.db.query(ONUDevice.mac_address, ONUDevice.id, ONUDevice.model).all()
}
for mac, onu_info in onu_info_dict.items():
onu_id = existing.get(mac)
entry = existing.get(mac)
if onu_id is None:
if entry is None:
# 新设备:只入库在线的
if onu_info.status != 'online':
continue
@@ -171,8 +173,12 @@ class CheckService:
self.db.add(onu)
self.db.flush()
self.db.add(NewDevice(onu_device_id=onu.id, olt_id=olt_id))
onu_id = onu.id
new_count += 1
onu_id = onu.id
else:
onu_id, onu_model = entry
if onu_info.model and not onu_model:
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update({"model": onu_info.model})
status = onu_info.status
distance_m = parse_distance(onu_info.distance_str)