python --minimalmodbus(RTU服务相关)

项目结构

在这里插入图片描述

依赖

# python 3.7
fastapi==0.103.2
loguru==0.7.3
minimalmodbus==2.0.1
pyinstaller==5.13.2
uvicorn==0.22.0

config.ini

[modbus]
port = COM1
address = 1
baudrate = 9600
bytesize = 8
parity = N
stopbits = 1
timeout = 1

[webserver]
port = 8001

main.py

# coding: utf-8
# python 3.7
import random
import time
import minimalmodbus
import uvicorn
import configparser
from fastapi import FastAPI, Request
from starlette.middleware.cors import CORSMiddleware
from loguru import logger
import os

class Setting(object):
    '''配置相关'''

    def __init__(self):
        self.base_dir = os.path.dirname(__file__)
        self.config_ini = os.path.join(self.base_dir, 'config.ini')
        self.config = configparser.ConfigParser()
        self.config.read(self.config_ini)
        self.modbus_config =  self.config['modbus']
        self.webserver_config = self.config['webserver']
        self._analysis_conf()
        self._init_instrument()

    def _analysis_conf(self):
        '''解析配置'''
        self.port = self.modbus_config.get('port')
        self.address = self.modbus_config.getint('address')
        self.baudrate = self.modbus_config.getint('baudrate')
        self.bytesize = self.modbus_config.getint('bytesize')
        self.parity = self.modbus_config.get('parity')
        self.stopbits = self.modbus_config.getint('stopbits')
        self.timeout = self.modbus_config.getfloat('timeout')
        self.websever_port = self.webserver_config.getint('port')

        if self.parity == 'E':
            self.parity = minimalmodbus.serial.PARITY_EVEN
        elif self.parity == 'O':
            self.parity = minimalmodbus.serial.PARITY_ODD
        else:
            self.parity = minimalmodbus.serial.PARITY_NONE

    def _init_instrument(self):
        '''实例化modbus'''
        self.instrument = minimalmodbus.Instrument(self.port, self.address)
        self.instrument.serial.baudrate = self.baudrate
        self.instrument.serial.bytesize = self.bytesize
        self.instrument.serial.parity = self.parity
        self.instrument.serial.stopbits = self.stopbits
        self.instrument.serial.timeout = self.timeout
        self.instrument.mode = minimalmodbus.MODE_RTU # rtu



app = FastAPI()
modbus = Setting()

app.add_middleware(  # 跨域
    CORSMiddleware,
    allow_origins=["*", ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.middleware("http")
async def middleware(request: Request, call_next):
    '''中间件'''
    now = time.strftime("%Y/%m/%d #H:%M:%S")
    client_host = request.client.host
    method = request.method
    path = request.url.path
    http_version = request.scope.get("http_version")
    logger.warning(f'当前请求IP为-->{client_host}')
    # print(f"[{now}] {method} {path} {http_version}")
    logger.debug(f'{method} {path}  HTTP/{http_version}')
    response = await call_next(request)
    return response


@app.post('/rtu_write') # 安全帽检测
async def rtu_write(request: Request) -> dict:
    '''
    写入寄存器
    @params address --> 写入寄存器地址;
    @params values  --> 写入的数据;数组;
    '''
    params = await request.json()  # 请求参数
    logger.warning(f'参数:【{params}】')
    address, values = [params.get(key) for key in params]
    try:
        modbus.instrument.write_registers(address, values)
        logger.success(f'写入成功')
        return {'code': 0, 'msg': 'success'}
    except Exception as e:
        logger.error(f'写入失败:【{e}】')
        return {'code': 500, 'msg': f'{e}'}

@app.post('/rtu_read') # 安全帽检测
async def rtu_write(request: Request) -> dict:
    '''
    写入寄存器
    @params address         --> 写入寄存器地址;
    @params start_address   --> 开始的寄存器地址;
    @params num_registers   --> 从开始地址读的具体个数;
    '''
    params = await request.json()  # 请求参数
    logger.warning(f'参数:【{params}】')
    address, start_address, num_registers = [params.get(key) for key in params]
    try:
        all_register_values =  modbus.instrument.read_registers(start_address, num_registers)
        # register_value = instrument.read_register(address) 读取单个寄存器的值
        logger.success(f"成功读取从寄存器地址 {start_address} 开始的 {num_registers} 个寄存器的值: {all_register_values}")
        return {'code': 0, 'msg': 'success', 'results': all_register_values}
    except Exception as e:
        logger.error(f'写入失败:【{e}】')
        return {'code': 500, 'msg': f'{e}'}

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=modbus.websever_port, workers=1)

文档

RTU服务API文档与配置详解

config.ini参数解释

参数名功能
modbus寄存器相关
webserverweb框架提供的服务配置
参数名功能类型
portwindows: COM1COM2 Linux: /dev/ttySx/ 或/dev/ttyUSBx 物理端口str
address从站地址int
baudrate波特率(默认:9600)int
bytesize数据位数。常见的数据位设置有 7 位或 8 位(默认:8)int
parity奇偶校验(可选:[‘E’, ‘O’, ‘N’]) 默认:Nstr
stopbits停止位;常见的停止位设置有 1 位或 2 位int
timeout设置为 1 秒,意味着主站最多等待 1 秒int

HTTP接口相关

给寄存器写数据

/rtu_write     # 请求方法: POST

请求参数

参数名功能参数类型
address写入的寄存器地址int
values写入的值;示例[1,2,3,4,5,6,7,8,9]数组list

返回值

参数名功能
code0(成功) 500(失败)
msg当code等于0时固定返回’success’ 当code等于500时 返回具体错误信息

读数据

/rtu_read  # 请求方法: POST

请求参数

参数名功能参数类型
address读的寄存器地址int
start_address需要读取开始地址int
num_registers从开始地址向后读取的具体数量; start_address 给3 num_registers给3 则读3,4,5的值int

调试工具(windows)

链接: https://pan.baidu.com/s/1oQ1khlS8Bo-VtYcwX7Wobw 提取码: 899k
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像风一样的男人@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值