合并冲突
This commit is contained in:
commit
71917122b6
@ -4,7 +4,7 @@ from fastapi import APIRouter, Depends, Query
|
|||||||
|
|
||||||
from app.core.response import success_response
|
from app.core.response import success_response
|
||||||
from app.core.security import verify_api_token
|
from app.core.security import verify_api_token
|
||||||
from app.schemas.platform import AiAlarmSettingIn, ChannelConfigIn, DeviceConfigIn, LineAlarmSettingIn, SystemConfigIn
|
from app.schemas.platform import AiAlarmSettingIn, ChannelConfigIn, DeviceConfigIn, LineAlarmSettingIn, NetConfigItem, SystemConfigIn, UartConfigItem
|
||||||
from app.services.platform_service import platform_service
|
from app.services.platform_service import platform_service
|
||||||
|
|
||||||
|
|
||||||
@ -21,6 +21,26 @@ def save_device_config(payload: DeviceConfigIn) -> Dict[str, Any]:
|
|||||||
return success_response(platform_service.save_device_config(payload))
|
return success_response(platform_service.save_device_config(payload))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/device/net", dependencies=[Depends(verify_api_token)])
|
||||||
|
def get_net_config(nic: str = Query(..., min_length=1)) -> Dict[str, Any]:
|
||||||
|
return success_response(platform_service.get_net_config(nic=nic), msg="获取网卡配置成功")
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/device/net", dependencies=[Depends(verify_api_token)])
|
||||||
|
def save_net_config(payload: NetConfigItem) -> Dict[str, Any]:
|
||||||
|
return success_response(platform_service.save_net_config(payload), msg="保存网卡配置成功")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/device/uart", dependencies=[Depends(verify_api_token)])
|
||||||
|
def get_uart_config(port: str = Query(..., min_length=1)) -> Dict[str, Any]:
|
||||||
|
return success_response(platform_service.get_uart_config(port=port), msg="获取串口配置成功")
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/device/uart", dependencies=[Depends(verify_api_token)])
|
||||||
|
def save_uart_config(payload: UartConfigItem) -> Dict[str, Any]:
|
||||||
|
return success_response(platform_service.save_uart_config(payload), msg="保存串口配置成功")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/channel", dependencies=[Depends(verify_api_token)])
|
@router.get("/channel", dependencies=[Depends(verify_api_token)])
|
||||||
def get_channel_config() -> Dict[str, Any]:
|
def get_channel_config() -> Dict[str, Any]:
|
||||||
return success_response(platform_service.get_channel_config(), msg="获取通道配置成功")
|
return success_response(platform_service.get_channel_config(), msg="获取通道配置成功")
|
||||||
|
|||||||
@ -15,9 +15,11 @@ from app.schemas.platform import (
|
|||||||
DeviceConfigIn,
|
DeviceConfigIn,
|
||||||
DeviceStatus,
|
DeviceStatus,
|
||||||
LineAlarmSettingIn,
|
LineAlarmSettingIn,
|
||||||
|
NetConfigItem,
|
||||||
RealtimeData,
|
RealtimeData,
|
||||||
SwitchControlIn,
|
SwitchControlIn,
|
||||||
SystemConfigIn,
|
SystemConfigIn,
|
||||||
|
UartConfigItem,
|
||||||
)
|
)
|
||||||
from app.ws.manager import ws_manager
|
from app.ws.manager import ws_manager
|
||||||
|
|
||||||
@ -44,16 +46,8 @@ class PlatformService:
|
|||||||
memory_store.set_status(status)
|
memory_store.set_status(status)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def save_device_config(self, payload: DeviceConfigIn) -> Dict[str, Any]:
|
def _default_device_config(self) -> Dict[str, Any]:
|
||||||
data = payload.model_dump()
|
return {
|
||||||
data["password"] = hash_password(payload.password)
|
|
||||||
path = self.config_repo.write_device_config(data)
|
|
||||||
device_result = self.device_client.send_device_config(payload)
|
|
||||||
return {"save_path": f"/config/{path.name}", **device_result}
|
|
||||||
|
|
||||||
def get_device_config(self) -> Dict[str, Any]:
|
|
||||||
current = self.config_repo.read_device_config()
|
|
||||||
data = {
|
|
||||||
"password": "",
|
"password": "",
|
||||||
"hardware_version": {
|
"hardware_version": {
|
||||||
"board_version": "B001.001.001",
|
"board_version": "B001.001.001",
|
||||||
@ -74,11 +68,114 @@ class PlatformService:
|
|||||||
{"port": "COM2", "baud": 115200, "parity": "NONE", "data_bits": 8, "stop_bits": 1, "protocol": "Modbus RTU"},
|
{"port": "COM2", "baud": 115200, "parity": "NONE", "data_bits": 8, "stop_bits": 1, "protocol": "Modbus RTU"},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
data.update(current)
|
|
||||||
|
def _merge_keyed_items(self, defaults: List[Dict[str, Any]], current: Any, key_field: str) -> List[Dict[str, Any]]:
|
||||||
|
merged = [dict(item) for item in defaults]
|
||||||
|
if not isinstance(current, list):
|
||||||
|
return merged
|
||||||
|
|
||||||
|
index_map = {
|
||||||
|
item.get(key_field): index
|
||||||
|
for index, item in enumerate(merged)
|
||||||
|
if isinstance(item, dict) and item.get(key_field) is not None
|
||||||
|
}
|
||||||
|
for item in current:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
key = item.get(key_field)
|
||||||
|
if key in index_map:
|
||||||
|
merged[index_map[key]].update(item)
|
||||||
|
else:
|
||||||
|
merged.append(dict(item))
|
||||||
|
return merged
|
||||||
|
|
||||||
|
def _upsert_keyed_item(self, items: List[Dict[str, Any]], payload: Dict[str, Any], key_field: str) -> List[Dict[str, Any]]:
|
||||||
|
key = payload.get(key_field)
|
||||||
|
updated = False
|
||||||
|
for index, item in enumerate(items):
|
||||||
|
if item.get(key_field) == key:
|
||||||
|
items[index] = payload
|
||||||
|
updated = True
|
||||||
|
break
|
||||||
|
if not updated:
|
||||||
|
items.append(payload)
|
||||||
|
return items
|
||||||
|
|
||||||
|
def _find_keyed_item(self, items: List[Dict[str, Any]], key_field: str, key_value: str) -> Optional[Dict[str, Any]]:
|
||||||
|
for item in items:
|
||||||
|
if item.get(key_field) == key_value:
|
||||||
|
return item
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _load_device_config_with_defaults(self) -> Dict[str, Any]:
|
||||||
|
current = self.config_repo.read_device_config()
|
||||||
|
defaults = self._default_device_config()
|
||||||
|
data = {
|
||||||
|
"password": current.get("password", "") if isinstance(current, dict) else "",
|
||||||
|
"hardware_version": dict(defaults["hardware_version"]),
|
||||||
|
"software_version": dict(defaults["software_version"]),
|
||||||
|
"net": [],
|
||||||
|
"uart": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
if isinstance(current, dict):
|
||||||
|
if isinstance(current.get("hardware_version"), dict):
|
||||||
|
data["hardware_version"].update(current["hardware_version"])
|
||||||
|
if isinstance(current.get("software_version"), dict):
|
||||||
|
data["software_version"].update(current["software_version"])
|
||||||
|
data["net"] = self._merge_keyed_items(defaults["net"], current.get("net"), "nic")
|
||||||
|
data["uart"] = self._merge_keyed_items(defaults["uart"], current.get("uart"), "port")
|
||||||
|
else:
|
||||||
|
data["net"] = self._merge_keyed_items(defaults["net"], None, "nic")
|
||||||
|
data["uart"] = self._merge_keyed_items(defaults["uart"], None, "port")
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def save_device_config(self, payload: DeviceConfigIn) -> Dict[str, Any]:
|
||||||
|
data = self._load_device_config_with_defaults()
|
||||||
|
payload_data = payload.model_dump()
|
||||||
|
data["hardware_version"] = payload_data["hardware_version"]
|
||||||
|
data["software_version"] = payload_data["software_version"]
|
||||||
|
data["net"] = self._merge_keyed_items(data["net"], payload_data["net"], "nic")
|
||||||
|
data["uart"] = self._merge_keyed_items(data["uart"], payload_data["uart"], "port")
|
||||||
|
if payload.password.strip():
|
||||||
|
data["password"] = hash_password(payload.password)
|
||||||
|
path = self.config_repo.write_device_config(data)
|
||||||
|
device_result = self.device_client.send_device_config(payload)
|
||||||
|
return {"save_path": f"/config/{path.name}", **device_result}
|
||||||
|
|
||||||
|
def get_device_config(self) -> Dict[str, Any]:
|
||||||
|
data = self._load_device_config_with_defaults()
|
||||||
# 不返回已保存的哈希密码,避免前端把哈希串直接显示到设置界面
|
# 不返回已保存的哈希密码,避免前端把哈希串直接显示到设置界面
|
||||||
data["password"] = ""
|
data["password"] = ""
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_net_config(self, nic: str) -> Dict[str, Any]:
|
||||||
|
device_config = self._load_device_config_with_defaults()
|
||||||
|
item = self._find_keyed_item(device_config["net"], "nic", nic)
|
||||||
|
if item is not None:
|
||||||
|
return item
|
||||||
|
return {"nic": nic, "ip": "", "mask": "", "gateway": "", "protocol": ""}
|
||||||
|
|
||||||
|
def save_net_config(self, payload: NetConfigItem) -> Dict[str, Any]:
|
||||||
|
device_config = self._load_device_config_with_defaults()
|
||||||
|
device_config["net"] = self._upsert_keyed_item(device_config["net"], payload.model_dump(), "nic")
|
||||||
|
path = self.config_repo.write_device_config(device_config)
|
||||||
|
return {"save_path": f"/config/{path.name}", "target": "net", "nic": payload.nic, "send_status": "成功"}
|
||||||
|
|
||||||
|
def get_uart_config(self, port: str) -> Dict[str, Any]:
|
||||||
|
device_config = self._load_device_config_with_defaults()
|
||||||
|
item = self._find_keyed_item(device_config["uart"], "port", port)
|
||||||
|
if item is not None:
|
||||||
|
return item
|
||||||
|
return {"port": port, "baud": 9600, "parity": "NONE", "data_bits": 8, "stop_bits": 1, "protocol": ""}
|
||||||
|
|
||||||
|
def save_uart_config(self, payload: UartConfigItem) -> Dict[str, Any]:
|
||||||
|
device_config = self._load_device_config_with_defaults()
|
||||||
|
device_config["uart"] = self._upsert_keyed_item(device_config["uart"], payload.model_dump(), "port")
|
||||||
|
path = self.config_repo.write_device_config(device_config)
|
||||||
|
return {"save_path": f"/config/{path.name}", "target": "uart", "port": payload.port, "send_status": "成功"}
|
||||||
|
|
||||||
def save_channel_config(self, payload: ChannelConfigIn) -> Dict[str, Any]:
|
def save_channel_config(self, payload: ChannelConfigIn) -> Dict[str, Any]:
|
||||||
path = self.config_repo.write_channel_config(payload.model_dump())
|
path = self.config_repo.write_channel_config(payload.model_dump())
|
||||||
device_result = self.device_client.send_channel_config(payload)
|
device_result = self.device_client.send_channel_config(payload)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"ch": 1,
|
"ch": 1,
|
||||||
"singal_type": "1-5v",
|
"singal_type": "1-5v",
|
||||||
"line_no": 2,
|
"line_no": 1,
|
||||||
"type": "UA",
|
"type": "UA",
|
||||||
"limit_low": 0.0,
|
"limit_low": 0.0,
|
||||||
"limit_high": 20.0
|
"limit_high": 20.0
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
|
"password": "ac9689e2272427085e35b9d3e3e8bed88cb3434828b43b86fc0596cad4c6e270",
|
||||||
"hardware_version": {
|
"hardware_version": {
|
||||||
"board_version": "B001.001.002",
|
"board_version": "B001.001.001",
|
||||||
"display_version": "S001.001.001",
|
"display_version": "S001.001.001",
|
||||||
"other_version": "Y001.001.001"
|
"other_version": "Y001.001.001"
|
||||||
},
|
},
|
||||||
@ -29,15 +29,15 @@
|
|||||||
"uart": [
|
"uart": [
|
||||||
{
|
{
|
||||||
"port": "COM1",
|
"port": "COM1",
|
||||||
"baud": 9600,
|
"baud": 19200,
|
||||||
"parity": "NONE",
|
"parity": "NONE",
|
||||||
"data_bits": 8,
|
"data_bits": 8,
|
||||||
"stop_bits": 1,
|
"stop_bits": 1,
|
||||||
"protocol": ""
|
"protocol": "Modbus RTU"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"port": "COM2",
|
"port": "COM2",
|
||||||
"baud": 115200,
|
"baud": 19200,
|
||||||
"parity": "NONE",
|
"parity": "NONE",
|
||||||
"data_bits": 8,
|
"data_bits": 8,
|
||||||
"stop_bits": 1,
|
"stop_bits": 1,
|
||||||
|
|||||||
@ -1,29 +1,62 @@
|
|||||||
{
|
{
|
||||||
"line_alarm_setting":
|
"line_alarm_setting": [
|
||||||
[
|
|
||||||
{
|
{
|
||||||
"line_no": 1,
|
"line_no": 1,
|
||||||
"over_limit_alarm": [
|
"over_limit_alarm": [
|
||||||
{
|
{
|
||||||
"category": "??",
|
"category": "电压",
|
||||||
"limit": 180.0,
|
"limit": 0.0,
|
||||||
"delay": 180,
|
"delay": 0,
|
||||||
"output_node": "??1",
|
"output_node": "开出1",
|
||||||
"enabled": true
|
"enabled": true
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"fault_alarm": [
|
"category": "电流",
|
||||||
{
|
"limit": 0.0,
|
||||||
"category": "PT??",
|
"delay": 0,
|
||||||
"limit": null,
|
"output_node": "开出2",
|
||||||
"delay": 180,
|
"enabled": true
|
||||||
"output_node": "??1",
|
},
|
||||||
"enabled": true
|
{
|
||||||
}
|
"category": "差流",
|
||||||
]
|
"limit": 0.0,
|
||||||
}
|
"delay": 0,
|
||||||
]
|
"output_node": "",
|
||||||
,
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "功率",
|
||||||
|
"limit": 0.0,
|
||||||
|
"delay": 0,
|
||||||
|
"output_node": "",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "频率",
|
||||||
|
"limit": 0.0,
|
||||||
|
"delay": 0,
|
||||||
|
"output_node": "",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fault_alarm": [
|
||||||
|
{
|
||||||
|
"category": "PT断线",
|
||||||
|
"limit": 0.0,
|
||||||
|
"delay": 0,
|
||||||
|
"output_node": "",
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "CT断线",
|
||||||
|
"limit": 0.0,
|
||||||
|
"delay": 0,
|
||||||
|
"output_node": "",
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"ai_alarm_setting": [
|
"ai_alarm_setting": [
|
||||||
{
|
{
|
||||||
"channel_no": 1,
|
"channel_no": 1,
|
||||||
@ -135,7 +168,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"system_config": {
|
"system_config": {
|
||||||
"time_sync": "manual",
|
"time_sync": "2026-05-18 17:05:28",
|
||||||
"brightness": 83,
|
"brightness": 83,
|
||||||
"screen_saver": 120
|
"screen_saver": 120
|
||||||
}
|
}
|
||||||
|
|||||||
@ -124,12 +124,16 @@ def test_config_query_endpoints(tmp_path) -> None:
|
|||||||
headers = {"X-API-Token": settings.auth_password}
|
headers = {"X-API-Token": settings.auth_password}
|
||||||
|
|
||||||
device_response = client.get("/api/config/device", headers=headers)
|
device_response = client.get("/api/config/device", headers=headers)
|
||||||
|
net_response = client.get("/api/config/device/net", headers=headers, params={"nic": "网卡一"})
|
||||||
|
uart_response = client.get("/api/config/device/uart", headers=headers, params={"port": "COM1"})
|
||||||
channel_response = client.get("/api/config/channel", headers=headers)
|
channel_response = client.get("/api/config/channel", headers=headers)
|
||||||
line_alarm_response = client.get("/api/config/line_alarm_setting", headers=headers, params={"line_no": 2})
|
line_alarm_response = client.get("/api/config/line_alarm_setting", headers=headers, params={"line_no": 2})
|
||||||
ai_alarm_response = client.get("/api/config/ai_alarm_setting", headers=headers)
|
ai_alarm_response = client.get("/api/config/ai_alarm_setting", headers=headers)
|
||||||
system_response = client.get("/api/config/system", headers=headers)
|
system_response = client.get("/api/config/system", headers=headers)
|
||||||
|
|
||||||
assert device_response.status_code == 200
|
assert device_response.status_code == 200
|
||||||
|
assert net_response.status_code == 200
|
||||||
|
assert uart_response.status_code == 200
|
||||||
assert channel_response.status_code == 200
|
assert channel_response.status_code == 200
|
||||||
assert line_alarm_response.status_code == 200
|
assert line_alarm_response.status_code == 200
|
||||||
assert ai_alarm_response.status_code == 200
|
assert ai_alarm_response.status_code == 200
|
||||||
@ -137,6 +141,8 @@ def test_config_query_endpoints(tmp_path) -> None:
|
|||||||
|
|
||||||
assert device_response.json()["data"]["password"] == ""
|
assert device_response.json()["data"]["password"] == ""
|
||||||
assert device_response.json()["data"]["net"][0]["ip"] == "192.168.1.10"
|
assert device_response.json()["data"]["net"][0]["ip"] == "192.168.1.10"
|
||||||
|
assert net_response.json()["data"]["nic"] == "网卡一"
|
||||||
|
assert uart_response.json()["data"]["port"] == "COM1"
|
||||||
assert channel_response.json()["data"]["ai_channel"][0]["singal_type"] == "4-20mA"
|
assert channel_response.json()["data"]["ai_channel"][0]["singal_type"] == "4-20mA"
|
||||||
assert line_alarm_response.json()["data"]["line_no"] == 2
|
assert line_alarm_response.json()["data"]["line_no"] == 2
|
||||||
assert line_alarm_response.json()["data"]["over_limit_alarm"][0]["category"] == "电流"
|
assert line_alarm_response.json()["data"]["over_limit_alarm"][0]["category"] == "电流"
|
||||||
@ -169,3 +175,87 @@ def test_save_line_alarm_setting_stores_list(tmp_path) -> None:
|
|||||||
assert saved["line_alarm_setting"][0]["line_no"] == 3
|
assert saved["line_alarm_setting"][0]["line_no"] == 3
|
||||||
finally:
|
finally:
|
||||||
platform_service.config_repo = old_repo
|
platform_service.config_repo = old_repo
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_device_net_and_uart_by_key(tmp_path) -> None:
|
||||||
|
old_repo = platform_service.config_repo
|
||||||
|
platform_service.config_repo = JsonConfigRepository(tmp_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
platform_service.config_repo.write_device_config(
|
||||||
|
{
|
||||||
|
"password": "hashed-password",
|
||||||
|
"hardware_version": {
|
||||||
|
"board_version": "B001.001.001",
|
||||||
|
"display_version": "S001.001.001",
|
||||||
|
"other_version": "Y001.001.001",
|
||||||
|
},
|
||||||
|
"software_version": {
|
||||||
|
"display_program": "001.001.001",
|
||||||
|
"communication_program": "001.001.001",
|
||||||
|
"measurement_program": "001.001.001",
|
||||||
|
},
|
||||||
|
"net": [
|
||||||
|
{"nic": "网卡一", "ip": "192.168.1.10", "mask": "255.255.255.0", "gateway": "192.168.1.1", "protocol": "Modbus TCP"},
|
||||||
|
{"nic": "网卡二", "ip": "192.168.1.56", "mask": "255.255.255.255", "gateway": "192.168.1.56", "protocol": "Modbus TCP"},
|
||||||
|
],
|
||||||
|
"uart": [
|
||||||
|
{"port": "COM1", "baud": 9600, "parity": "NONE", "data_bits": 8, "stop_bits": 1, "protocol": ""},
|
||||||
|
{"port": "COM2", "baud": 115200, "parity": "NONE", "data_bits": 8, "stop_bits": 1, "protocol": "Modbus RTU"},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
headers = {"X-API-Token": settings.auth_password}
|
||||||
|
|
||||||
|
net_save = client.post(
|
||||||
|
"/api/config/device/net",
|
||||||
|
headers=headers,
|
||||||
|
json={"nic": "网卡二", "ip": "10.10.10.2", "mask": "255.255.255.0", "gateway": "10.10.10.1", "protocol": "IEC104"},
|
||||||
|
)
|
||||||
|
uart_save = client.post(
|
||||||
|
"/api/config/device/uart",
|
||||||
|
headers=headers,
|
||||||
|
json={"port": "COM2", "baud": 4800, "parity": "EVEN", "data_bits": 8, "stop_bits": 1, "protocol": "DLT645"},
|
||||||
|
)
|
||||||
|
full_save = client.post(
|
||||||
|
"/api/config/device",
|
||||||
|
headers=headers,
|
||||||
|
json={
|
||||||
|
"password": "",
|
||||||
|
"hardware_version": {
|
||||||
|
"board_version": "B001.001.003",
|
||||||
|
"display_version": "S001.001.001",
|
||||||
|
"other_version": "Y001.001.001",
|
||||||
|
},
|
||||||
|
"software_version": {
|
||||||
|
"display_program": "001.001.001",
|
||||||
|
"communication_program": "001.001.001",
|
||||||
|
"measurement_program": "001.001.001",
|
||||||
|
},
|
||||||
|
"net": [
|
||||||
|
{"nic": "网卡一", "ip": "172.16.1.10", "mask": "255.255.255.0", "gateway": "172.16.1.1", "protocol": "Modbus TCP"}
|
||||||
|
],
|
||||||
|
"uart": [
|
||||||
|
{"port": "COM1", "baud": 19200, "parity": "ODD", "data_bits": 8, "stop_bits": 1, "protocol": "Modbus RTU"}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert net_save.status_code == 200
|
||||||
|
assert uart_save.status_code == 200
|
||||||
|
assert full_save.status_code == 200
|
||||||
|
|
||||||
|
saved = platform_service.config_repo.read_device_config()
|
||||||
|
net_map = {item["nic"]: item for item in saved["net"]}
|
||||||
|
uart_map = {item["port"]: item for item in saved["uart"]}
|
||||||
|
|
||||||
|
assert net_map["网卡一"]["ip"] == "172.16.1.10"
|
||||||
|
assert net_map["网卡二"]["ip"] == "10.10.10.2"
|
||||||
|
assert net_map["网卡二"]["protocol"] == "IEC104"
|
||||||
|
assert uart_map["COM1"]["baud"] == 19200
|
||||||
|
assert uart_map["COM2"]["baud"] == 4800
|
||||||
|
assert uart_map["COM2"]["protocol"] == "DLT645"
|
||||||
|
assert saved["password"] == "hashed-password"
|
||||||
|
finally:
|
||||||
|
platform_service.config_repo = old_repo
|
||||||
|
|||||||
@ -369,6 +369,11 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- `net` 按 `nic` 标识各网卡配置
|
||||||
|
- `uart` 按 `port` 标识各串口配置
|
||||||
|
- 界面如需按单个网卡或单个串口精确读取,可调用后续独立查询接口
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 4. POST /api/config/device
|
#### 4. POST /api/config/device
|
||||||
@ -428,9 +433,100 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
**返回data**:`{"save_path":"/config/device.json","send_status":"成功"}`
|
**返回data**:`{"save_path":"/config/device.json","send_status":"成功"}`
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 设备整体保存时,网卡配置按 `nic` 合并更新
|
||||||
|
- 串口配置按 `port` 合并更新
|
||||||
|
- 未出现在本次提交中的其他网卡或串口配置会保留,不会因数组顺序变化被误覆盖
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 5. GET /api/config/channel
|
#### 5. GET /api/config/device/net
|
||||||
|
|
||||||
|
**作用**:按网卡标识读取单个网卡配置
|
||||||
|
**参数**:
|
||||||
|
- `nic=网卡一`:按 `nic` 查询对应网卡信息
|
||||||
|
**返回data**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nic": "网卡一",
|
||||||
|
"ip": "192.168.1.10",
|
||||||
|
"mask": "255.255.255.0",
|
||||||
|
"gateway": "192.168.1.1",
|
||||||
|
"protocol": "Modbus TCP"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
#### 6. POST /api/config/device/net
|
||||||
|
|
||||||
|
**作用**:按网卡标识保存单个网卡配置
|
||||||
|
**请求body参数**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nic": "网卡一",
|
||||||
|
"ip": "192.168.1.10",
|
||||||
|
"mask": "255.255.255.0",
|
||||||
|
"gateway": "192.168.1.1",
|
||||||
|
"protocol": "Modbus TCP"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回data**:`{"save_path":"/config/device.json","target":"net","nic":"网卡一","send_status":"成功"}`
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 服务端会根据 `nic` 更新对应网卡对象
|
||||||
|
- 若不存在相同 `nic`,则追加到 `net` 数组
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
#### 7. GET /api/config/device/uart
|
||||||
|
|
||||||
|
**作用**:按串口标识读取单个串口配置
|
||||||
|
**参数**:
|
||||||
|
- `port=COM1`:按 `port` 查询对应串口信息
|
||||||
|
**返回data**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"port": "COM1",
|
||||||
|
"baud": 9600,
|
||||||
|
"parity": "NONE",
|
||||||
|
"data_bits": 8,
|
||||||
|
"stop_bits": 1,
|
||||||
|
"protocol": "Modbus RTU"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
#### 8. POST /api/config/device/uart
|
||||||
|
|
||||||
|
**作用**:按串口标识保存单个串口配置
|
||||||
|
**请求body参数**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"port": "COM1",
|
||||||
|
"baud": 9600,
|
||||||
|
"parity": "NONE",
|
||||||
|
"data_bits": 8,
|
||||||
|
"stop_bits": 1,
|
||||||
|
"protocol": "Modbus RTU"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回data**:`{"save_path":"/config/device.json","target":"uart","port":"COM1","send_status":"成功"}`
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 服务端会根据 `port` 更新对应串口对象
|
||||||
|
- 若不存在相同 `port`,则追加到 `uart` 数组
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
#### 9. GET /api/config/channel
|
||||||
|
|
||||||
**作用**:读取通道配置,用于通道配置界面打开时回显当前参数
|
**作用**:读取通道配置,用于通道配置界面打开时回显当前参数
|
||||||
**参数**:无
|
**参数**:无
|
||||||
@ -445,7 +541,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 6. POST /api/config/channel
|
#### 10. POST /api/config/channel
|
||||||
|
|
||||||
**作用**:提交AI/AO通道配置(AI:12通道,AO:12通道)
|
**作用**:提交AI/AO通道配置(AI:12通道,AO:12通道)
|
||||||
**请求body参数**:
|
**请求body参数**:
|
||||||
@ -461,7 +557,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 7. GET /api/config/line\_alarm\_setting
|
#### 11. GET /api/config/line\_alarm\_setting
|
||||||
|
|
||||||
**作用**:读取线路报警设置,用于报警设置界面打开时回显当前线路参数
|
**作用**:读取线路报警设置,用于报警设置界面打开时回显当前线路参数
|
||||||
**参数**:
|
**参数**:
|
||||||
@ -493,7 +589,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 8. POST /api/config/line\_alarm\_setting
|
#### 12. POST /api/config/line\_alarm\_setting
|
||||||
|
|
||||||
**作用**:提交定值报警阈值配置
|
**作用**:提交定值报警阈值配置
|
||||||
**请求body参数**:
|
**请求body参数**:
|
||||||
@ -564,7 +660,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 9. GET /api/config/ai\_alarm\_setting
|
#### 13. GET /api/config/ai\_alarm\_setting
|
||||||
|
|
||||||
**作用**:读取AI报警设置,用于报警设置界面打开时回显当前AI报警参数
|
**作用**:读取AI报警设置,用于报警设置界面打开时回显当前AI报警参数
|
||||||
**参数**:无
|
**参数**:无
|
||||||
@ -586,7 +682,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 10. POST /api/config/ai\_alarm\_setting
|
#### 14. POST /api/config/ai\_alarm\_setting
|
||||||
|
|
||||||
**作用**:提交AI报警设置
|
**作用**:提交AI报警设置
|
||||||
**请求body参数**:
|
**请求body参数**:
|
||||||
@ -616,7 +712,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
**返回data**:`{"save_path":"/config/setting.json","send_status":"成功"}`
|
**返回data**:`{"save_path":"/config/setting.json","send_status":"成功"}`
|
||||||
|
|
||||||
#### 11. GET /api/config/system
|
#### 15. GET /api/config/system
|
||||||
|
|
||||||
**作用**:读取系统设置,用于系统设置界面打开时回显当前参数
|
**作用**:读取系统设置,用于系统设置界面打开时回显当前参数
|
||||||
**参数**:无
|
**参数**:无
|
||||||
@ -632,7 +728,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 12. POST /api/config/system
|
#### 16. POST /api/config/system
|
||||||
|
|
||||||
**作用**:提交系统对时、灯光配置
|
**作用**:提交系统对时、灯光配置
|
||||||
**请求body参数**:
|
**请求body参数**:
|
||||||
@ -649,7 +745,7 @@ Python FastAPI服务层(RESTful接口 + WebSocket推送 + 数据处理)
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 13. GET /api/alarm/list
|
#### 17. GET /api/alarm/list
|
||||||
|
|
||||||
**作用**:分页查询历史报警
|
**作用**:分页查询历史报警
|
||||||
**参数**:
|
**参数**:
|
||||||
@ -691,7 +787,7 @@ GET /api/alarm/list?page=1&size=20&no=L1&type=current&start_time=2026-05-16T10:3
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
#### 14. POST /api/control/switch
|
#### 18. POST /api/control/switch
|
||||||
|
|
||||||
**作用**:下发开关量控制指令
|
**作用**:下发开关量控制指令
|
||||||
**请求body参数**:
|
**请求body参数**:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user