From f7131cf425c3d9813e865a22bc5a9335fc4f5eac Mon Sep 17 00:00:00 2001 From: sunyugang Date: Mon, 29 Sep 2025 16:49:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 ++ .idea/hvac_end_python.iml | 8 ++ .idea/inspectionProfiles/Project_Default.xml | 13 ++++ .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/misc.xml | 4 + .idea/modules.xml | 8 ++ .idea/vcs.xml | 6 ++ api/modbus_api.py | 32 ++++++++ api/schemas/modbus_schemas.py | 16 ++++ app/app_config.py | 20 +++++ common/reponse_code.py | 34 ++++++++ main.py | 5 ++ modbus/modbus_util.py | 77 +++++++++++++++++++ requirement.txt | 3 + 14 files changed, 240 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/hvac_end_python.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 api/modbus_api.py create mode 100644 api/schemas/modbus_schemas.py create mode 100644 app/app_config.py create mode 100644 common/reponse_code.py create mode 100644 main.py create mode 100644 modbus/modbus_util.py create mode 100644 requirement.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/hvac_end_python.iml b/.idea/hvac_end_python.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/.idea/hvac_end_python.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..5a114f2 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..19656c4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5f9c260 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/api/modbus_api.py b/api/modbus_api.py new file mode 100644 index 0000000..ac6d340 --- /dev/null +++ b/api/modbus_api.py @@ -0,0 +1,32 @@ +from fastapi import APIRouter +from api.schemas.modbus_schemas import ModbusIn, ModbusOut +from common import reponse_code as rc +from modbus.modbus_util import write_register, read_register_float_value + + +modbus = APIRouter() + + +@modbus.post("/write") +def write_float_value(modbusIn: ModbusIn): + if modbusIn.type == 'float': + value = float(modbusIn.value) + elif modbusIn.type == 'short': + value = int(modbusIn.value) + success, msg = write_register(host=modbusIn.host, port=modbusIn.port, + address=modbusIn.address, value=value) + if success: + return rc.response_success("修改成功") + else: + return rc.response_error(msg) + + +@modbus.post("/read") +def write_float_value(modbusOut: ModbusOut): + success, result_dict = read_register_float_value(host=modbusOut.host, port=modbusOut.port, address=modbusOut.address) + if success: + return rc.response_success(msg="读取成功", data=result_dict) + else: + return rc.response_error('读取失败') + + diff --git a/api/schemas/modbus_schemas.py b/api/schemas/modbus_schemas.py new file mode 100644 index 0000000..6f3dcf4 --- /dev/null +++ b/api/schemas/modbus_schemas.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel, Field +from typing import Optional + + +class ModbusIn(BaseModel): + host: Optional[str] = Field(..., description="地址") + port: Optional[int] = Field(..., description="端口") + address: Optional[int] = Field(..., description="内存地址") + value: Optional[str] = Field(..., description="写入的值") + type: Optional[str] = Field(..., description="写入值的类型") + + +class ModbusOut(BaseModel): + host: Optional[str] = Field(..., description="地址") + port: Optional[int] = Field(..., description="端口") + address: Optional[list[int]] = Field(..., description="内存地址") diff --git a/app/app_config.py b/app/app_config.py new file mode 100644 index 0000000..deaa348 --- /dev/null +++ b/app/app_config.py @@ -0,0 +1,20 @@ +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware + +from api.modbus_api import modbus + +app = FastAPI() + + +''' +添加CORS中间件,允许跨域请求 +''' +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +app.include_router(modbus, prefix="/modbus", tags=["modbus的api"]) diff --git a/common/reponse_code.py b/common/reponse_code.py new file mode 100644 index 0000000..da51492 --- /dev/null +++ b/common/reponse_code.py @@ -0,0 +1,34 @@ +from fastapi.responses import JSONResponse, Response +from fastapi import status + + +def response_code_view(code: int,msg: str) -> Response: + return JSONResponse( + status_code=code, + content={ + 'code': code, + 'msg': msg + } + ) + + +def response_success(msg: str = "查询成功", data: object = None): + return JSONResponse( + status_code=status.HTTP_200_OK, + content={ + 'code': 200, + 'msg': msg, + 'data': data, + } + ) + + +def response_error(msg:str): + return JSONResponse( + status_code=status.HTTP_200_OK, + content={ + 'code': 500, + 'msg': msg, + 'data': None, + } + ) diff --git a/main.py b/main.py new file mode 100644 index 0000000..15e92c6 --- /dev/null +++ b/main.py @@ -0,0 +1,5 @@ +import uvicorn +from app.app_config import app + +if __name__ == '__main__': + uvicorn.run("main:app", port=8991, reload=True, host="0.0.0.0") diff --git a/modbus/modbus_util.py b/modbus/modbus_util.py new file mode 100644 index 0000000..b5311d3 --- /dev/null +++ b/modbus/modbus_util.py @@ -0,0 +1,77 @@ +from pymodbus.client.tcp import ModbusTcpClient +from pymodbus.exceptions import ModbusException +import struct + + +def read_register_float_value(host: str, port: int, address: list[int]): + """ + 从modbus 读取数据 + :param port: 端口 + :param host: 地址 + :param address: 减去40000的偏移量 + :return: float值 + """ + result_dict = {} + client = ModbusTcpClient(host=host, port=port) + try: + # 连接到 Modbus 设备 + if client.connect(): + for add in address: + # 从起始地址为 40002 的寄存器读取数据(Modbus 地址从 0 开始,所以 40003 对应 40002) + result = client.read_holding_registers(address=add, count=2) # 读取 2 个寄存器,因为一个 float 占用 2 个寄存器 + if not result.isError(): + # 获取寄存器值列表 + register_values = result.registers + # 将寄存器值转换为字节表示 + packed_bytes = bytes() + for value in register_values: + packed_bytes += value.to_bytes(2, byteorder='big') + # 将字节表示转换为浮点数 + float_value = struct.unpack('>f', packed_bytes)[0] # 使用大端序 + result_dict[add] = float_value + else: + print("读取数据失败:", result) + return False, None + return True, result_dict + else: + print("无法连接到 Modbus 设备") + return False, None + except ModbusException as e: + print("发生 Modbus 异常:", e) + return False, None + finally: + # 关闭连接 + client.close() + + +def write_register(host: str, port: int, address: int, value): + """ + 写数据 + :param host: 地址 + :param port: 端口 + :param address: 地址 + :param value: 值 + :return: + """ + client = ModbusTcpClient(host=host, port=port) + try: + # 连接到 Modbus 设备 + if client.connect(): + # 将浮点数转换为字节表示 + packed_float = struct.pack('>f', value) + # 将字节转换为 16 位整数列表,因为每个寄存器是 16 位 + registers = [int.from_bytes(packed_float[i:i + 2], byteorder='big', signed=False) for i in + range(0, len(packed_float), 2)] + # 向起始地址为 40000 的寄存器写入数据(Modbus 地址从 0 开始,所以 40001 对应 40000) + result = client.write_registers(address=address, values=registers) + if not result.isError(): + return True, "浮点数写入成功" + else: + return False, "浮点数写入失败:" + result + else: + return False, "无法连接到 Modbus 设备" + except ModbusException as e: + return False, "发生 Modbus 异常:" + e + finally: + # 关闭连接 + client.close() \ No newline at end of file diff --git a/requirement.txt b/requirement.txt new file mode 100644 index 0000000..af2843f --- /dev/null +++ b/requirement.txt @@ -0,0 +1,3 @@ +fastapi==0.112.2 +uvicorn==0.32.1 +pymodbus==3.8.3 \ No newline at end of file