Skip to main content

一款用于自动化执行串口指令的脚本,支持多设备、多指令的串行和并行执行

Project description

AutoCom

一款用于自动化执行串口指令的脚本,支持多设备、多指令的串行和并行执行。

Cross Platform Serial Communication Multi-Device Automation PyPI


📑 目录

📁 项目结构

AutoCom/
├── 📂 components/         # 核心组件模块
│   └── *.py
├── 📂 utils/              # 工具类和辅助函数
│   └── *.py
├── 📂 tests/              # 测试文件目录
│   └── *.py
├── 📂 scripts/            # 构建和维护脚本
│   └── *.py
├── 📂 docs/               # 项目文档
│   └── *.md
├── 📂 dicts/              # 字典配置文件目录
├── 📂 configs/            # 设备配置文件目录
├── AutoCom.py             # 主程序入口
├── cli.py                 # 命令行接口
├── version.py             # 版本信息
├── __init__.py            # 包初始化文件
└── README.md              # 项目说明文档

📂 目录说明

  • components/ - 核心功能组件,包含设备管理、指令执行、数据存储等核心模块
  • utils/ - 工具函数和操作处理器,包含自定义 Action 扩展接口
  • scripts/ - 开发和维护脚本
    • dev.py - 统一开发工具,集成测试、构建、发布等功能
    • update_actions_doc.py - 更新 Actions.md 文档
  • docs/ - 项目文档
    • Started.md - 快速开始指南
    • DEV.md - 开发指南和工具说明
    • About.md - 项目详细说明和设计文档
    • ToDO.md - 待办事项和未来计划
    • Actions.md - 所有 Action 操作项的详细说明
  • dicts/ - 存放指令字典配置文件
  • configs/ - 存放设备配置模板文件
  • temps/ - 临时数据存储,运行时自动创建
  • device_logs/ - 设备执行日志,运行时自动创建

安装

从 PyPI 安装(推荐)

pip install autocom

从 GitHub 直接安装

无需等待 PyPI 发布,可以直接从 GitHub 安装最新版本:

# 从 main 分支安装最新版本
pip install git+https://github.com/iFishin/AutoCom.git

# 从特定版本安装 (推荐)
pip install git+https://github.com/iFishin/AutoCom.git@v1.0.0

从源码安装

# 克隆仓库
git clone https://github.com/iFishin/AutoCom.git
cd AutoCom

# 安装依赖
pip install -r requirements.txt

# 开发模式安装(可编辑)
pip install -e .

手动打包安装

如果你想自己打包:

python scripts/dev.py build
pip install dist/autocom-<version>-py3-none-any.whl

🚀 快速开始

命令行使用

安装后,可以直接使用 autocom 命令:

# 执行字典文件(循环3次)
autocom -d dicts/dict.json -l 3

# 无限循环模式(按 Ctrl+C 停止)
autocom -d dicts/dict.json -i

# 使用配置文件
autocom -d dicts/dict.json -c configs/config.json

# 执行文件夹内所有字典文件
autocom -f dicts/

# 监控模式(监听文件夹,自动执行新文件)
autocom -m temps/

Python API 使用

from autocom import CommandDeviceDict, CommandExecutor, CommonUtils

# 加载配置
dict_data = {...}  # 你的配置字典
device_dict = CommandDeviceDict(dict_data)

# 创建执行器
executor = CommandExecutor(device_dict)

# 执行指令
result = executor.execute()

# 清理资源
device_dict.close_all_devices()
executor.data_store.stop()

从源代码中执行

  • 单个字典文件执行

python cli.py -d <xxx.json> -l <times> [-c <configFile>]

  • 文件夹内所有字典文件顺序执行

python cli.py -f <dictFilePath> -c <configFile>

文件夹内的文件命名得加上前缀区分执行顺序:[<order>]<filename>.json

  • 监听文件夹内新文件

python cli.py -m <monitoredFilePath>

格式框架

设备

Devices

"Devices": [
        {
            "name": "DeviceA",
            "status": "enabled",
            "port": "COM65",
            "baud_rate": 115200,
            "stop_bits": 1,
            "parity": null,
            "data_bits": 8,
            "flow_control": {
                "xon_xoff": false,
                "rts_cts": false,
                "dsr_dtr": false
            },
            "dtr": false,
            "rts": false
        },
        {
            "name": "DeviceB",
            "status": "disabled",
            "port": "COM64",
            "baud_rate": 115200,
            "stop_bits": 1,
            "parity": null,
            "data_bits": 8,
            "flow_control": {
                "xon_xoff": false,
                "rts_cts": false,
                "dsr_dtr": false
            },
            "dtr": false,
            "rts": false
        }
    ]

设备参数

Device 内容 作用
name 设备名称(如 "DeviceA"、"DeviceB") 标识不同的设备
status 设备状态("enabled"/"disabled") 表示设备当前状态
port 串口名称(如 "COM65") 指定设备物理连接端口
baud_rate 波特率(如 115200) 设定通信速率
stop_bits 停止位(1/2) 设定停止位
parity 奇偶校验("None"/"Even"/"Odd") 设定奇偶校验
data_bits 数据位(5/6/7/8) 设定数据位
flow_control 流控制配置 设定流控制
dtr DTR信号(true/false) 设定DTR信号
rts RTS信号(true/false) 设定RTS信号
monitor 是否持续监听设备(true/false) 设定是否持续监听日志

配置执行设备的基本信息。

monitor是针对Debug串口设计的持续日志监听功能,当该属性开启之后,会单独启动一个线程持续监听来自串口的日志。默认情况下是关闭,默认的监听逻辑为有指令发送至该串口后,才会监听一次来自串口的返回数据。

设备列表全局配置

更新加入了ConfigForDevices属性块,可以利用全局配置来减少设备列表的属性编辑

覆盖逻辑为:ConfigForDevices中的键值对只会替换Devices中相对应不存在的键值对,相反的,如果Devices中存在status: "enabled",且你在ConfigForDevices中也设置了该属性,则不会利用全局配置来替换。

With ConfigForDevices
 "ConfigForDevices": {
        "status": "enabled",
        "stop_bits": 1,
        "parity": null,
        "data_bits": 8,
        "flow_control": {
            "xon_xoff": false,
            "rts_cts": false,
            "dsr_dtr": false
        },
        "dtr": false,
        "rts": false
    },
    "Devices": [
        {
            "name": "DeviceA",
            "port": "COM14",
            "baud_rate": 115200
        },
        {
            "name": "DebugA",
            "port": "COM13",
            "baud_rate": 115200,
            "monitor": true
        },
        {
            "name": "DeviceB",
            "port": "COM36",
            "baud_rate": 115200
        }
    ]
</code>
</pre> </details>
<h3>操作项</h3>
<p>新版中,已剥离了Actions操作项的函数,单独设计成一个扩展的类,Actions类中包含了所有操作项的实现逻辑。用户可以根据自己的需求,自定义操作项的实现逻辑,方便扩展和维护。</p>
<blockquote>
<p>📖 <strong>详细文档</strong>: 查看 <a href="docs/Actions.md">docs/Actions.md</a> 获取所有操作项的完整说明、参数详解和使用示例。</p>
<p>actions也是一个list类型,包含了针对特定情境的处理方式,如果指令包含了相应的actions项,则会顺序执行列表内的所有action项。</p>
</blockquote>
<h4>操作项全局配置</h4>
<blockquote>
<p>更新加入了<code>ConfigForActions</code>属性块,可以引入自定义的操作项配置。</p>
</blockquote>
<details>
<summary><font size="6">With ConfigForActions</font></summary>
<pre><code class="language-json">
{
  "ConfigForActions": {
    "handler_class": "utils.custom_actions.CustomActionHandler"
  },
  "Devices": [...],
  "Commands": [...]
}
</code>
</pre> </details>
<h4>操作项编写指南</h4>
<p>在分离ActionHandler之后,在<code>utils/ActionHandler</code>中编写了常用到的action操作,下面用一个简单的例子来讲解自定义Action编写方法:</p>
<pre lang="python"><code>def handle_test(self, text, command, response, context):
    """
    测试功能

    用法:
    {
        "test": "test_message"
    }
    """
    test_message = self.handle_variables_from_str(text)
    CommonUtils.print_log_line(f"ℹ Test action executed with message: {test_message}")
    CommonUtils.print_log_line("")
    return True

首先先了解这个Action是指的什么。上面注释中所描述的{ "test": "test_message" }是一个Action项,也是一个Object对象,这个Action项的名称为test,而这个Action的内容则是test_message。在执行时,这个Action会被传入到handle_test函数中。 然后看看传入的参数列表:

self这个是指向当前ActionHandler实例的引用,这里必须包含,用于注册ActionHandler的函数 ② text这个是传入action所含的Object内容,这里是指{"test": "test_message"}中的"test_message"部分。如果action名包含的是一个Object对象,则会将该对象传入,这里需要注意类型对应。 ③ command这个是指当前执行的指令对象,也就是指令字典中的command属性内容。 ④ response这个是指当前指令执行后响应内容,这个类型是List,得注意。 ⑤ context这个是指当前执行上下文,包含了当前设备、指令等信息。这里的context内容目前为:

{
        "device": device,
        "device_name": device_name,
        "cmd_str": cmd_str,
        "expected_responses": updated_expected_responses
}

由于ActionHandler扩展性太多,后续可能变更,请以实际代码逻辑为准。

指令

Commands
"Commmands": [
        {
            "command": "AT+COMMAND1",
            "status": "enabled",
            "expected_responses": [
                "OK",
                "RDY"
            ],
            "device": "DeviceA",
            "order": 1,
            "parameters": [],
            "timeout": 2000,
            "concurrent_strategy": "parallel",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "success_response_actions": [
            ],
            "error_actions": [
                {
                    "retry": 3
                }
            ],
            "error_response_actions": [
            ]
        },
        {
            "command": "AT+COMMAND2",
            "status": "enabled",
            "expected_responses": [
                "OK"
            ],
            "device": "DeviceA",
            "order": 3,
            "parameters": [],
            "timeout": 3000,
            "concurrent_strategy": "sequential",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "success_response_actions": {
                "GOT_IP": [
                    {
                        "print": "GOT_IP"
                    }
                ]
            },
            "error_actions": [
                {
                    "retry": 3
                }
            ],
            "error_response_actions": {
                "WLAN_DISCONNECTED": [
                    {
                        "print": "DISCONNECTED"
                    }
                ],
                "SCAN_NO_AP": [
                    {
                        "print": "NO AP"
                    }
                ]
            }
        }
    ]
</code>
</pre> </details>
<h4>指令参数</h4>
<table>
<thead>
<tr>
<th>Command</th>
<th>内容</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>command</td>
<td>AT指令字符串(如 "AT+RST")</td>
<td>发送给设备的具体指令</td>
</tr>
<tr>
<td>hex_mode</td>
<td>是否以十六进制模式发送指令(true/false)</td>
<td>设定指令发送格式</td>
</tr>
<tr>
<td>status</td>
<td>指令状态("enabled"/"disabled")</td>
<td>指定指令是否可用</td>
</tr>
<tr>
<td>expected_responses</td>
<td>预期响应列表(如 ["OK","RDY"])</td>
<td>判断指令执行成功条件</td>
</tr>
<tr>
<td>device</td>
<td>目标设备名称</td>
<td>指定执行指令的设备</td>
</tr>
<tr>
<td>order</td>
<td>执行顺序(数字)</td>
<td>确定指令执行顺序</td>
</tr>
<tr>
<td><u>parameters</u></td>
<td>指令参数列表</td>
<td>提供指令所需参数</td>
</tr>
<tr>
<td>timeout</td>
<td>超时时间(毫秒)</td>
<td>设定指令执行时限</td>
</tr>
<tr>
<td>concurrent_strategy</td>
<td>"sequential""parallel"</td>
<td>设定指令并发策略</td>
</tr>
<tr>
<td><strong>error_actions</strong></td>
<td>错误处理配置</td>
<td>定义错误响应处理方式</td>
</tr>
<tr>
<td><strong>success_actions</strong></td>
<td>成功后续操作</td>
<td>指定成功后的附加动作</td>
</tr>
<tr>
<td><strong>error_response_actions</strong></td>
<td>错误响应后续操作</td>
<td>特定错误响应后的动作</td>
</tr>
<tr>
<td><strong>success_response_actions</strong></td>
<td>成功响应后续操作</td>
<td>特定成功响应后的动作</td>
</tr>
<tr>
<td><del>dependencies</del></td>
<td>依赖指令列表</td>
<td>设定指令执行依赖项</td>
</tr>
</tbody>
</table>
<blockquote>
<ul>
<li>command</li>
<li>expected_responses</li>
<li>parameters</li>
</ul>
<p>expected_responses 的判断逻辑为:顺序匹配,只有所有预期响应都匹配成功,才认为指令执行成功</p>
<p>上面参数都支持向临时数据文件中取用变量,取用逻辑为:<code>{variable_name}</code></p>
<hr />
<ul>
<li>variable_name</li>
</ul>
<p>这个变量的命名格式是字母和下划线的混合</p>
<p>如果临时数据文件中存在该变量则返回对应的值</p>
<p>如果临时数据文件中不存在该变量,则会原始文本输出{variable_name}</p>
<hr />
<ul>
<li>concurrent_strategy</li>
</ul>
<p>脚本中的并发策略为:为相邻参与并行执行的指令按照设备分组,然后为每个设备创建一个线程,并行执行完成后返回直接结果,线程设置了30ms超时时限,防止阻塞。</p>
<hr />
<ul>
<li>order</li>
</ul>
<p>这个执行序号如若遇到序号相同的情形,指令重排之后,相同序号的指令则会按照原始排列出现的顺序执行</p>
</blockquote>
<h4>指令列表全局配置</h4>
<blockquote>
<p>覆盖逻辑同<code>ConfigForDevices</code>,用于简化重复的属性配置。</p>
</blockquote>
<details>
<summary><font size="6">With ConfigForDevices</font></summary>
<pre><code class="language-json">
    "ConfigForCommands": {
        "status": "enabled",
        "timeout": 1000,
        "concurrent_strategy": "sequential",
        "error_actions": [
            {
                "retry": 1
            }
        ]
    },
    "Commands": [
        {
            "command": "AT+RST",
            "expected_responses": [
                "OK",
                "RDY"
            ],
            "device": "DeviceA",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "order": 1
        },
        {
            "command": "AT+ECHO=1",
            "expected_responses": [
                "OK"
            ],
            "device": "DeviceA",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "order": 1
        },
        {
            "command": "AT+RST",
            "expected_responses": [
                "OK",
                "RDY"
            ],
            "device": "DeviceB",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "order": 1
        },
        {
            "command": "AT+ECHO=1",
            "expected_responses": [
                "OK"
            ],
            "device": "DeviceB",
            "success_actions": [
                {
                    "set_status": "disabled"
                }
            ],
            "order": 1
        }
    ]
</code>
</pre> </details>
<h3>临时性数据</h3>
<details>
<summary><font size="6">Temp-Data</font></summary>
<pre><code class="language-json">
{
  "DeviceB": {
    "fish": "RST",
    "gatt_char": "\"36f5\"",
    "ble_address": "\"D87A3B6D522B\""
  },
  "DeviceA": {
    "gatt_char": "\"36f5\""
  }
}
</code>
</pre> </details>
> Temp-Data可当作一个简易数据库的功能,用于存取执行过程中的各类临时性变量。
<p>目前这个数据存取使用一个<code>DataStore</code>类来控制,该类目前提供了两个方法:</p>
<ul>
<li><strong>store_data</strong></li>
</ul>
<blockquote>
<p>用于存储变量到指定设备名中去。操作方法为(data_store为实例):</p>
<p><code>data_store.store_data(<device_name>, <variable_name>, <value>)</code></p>
</blockquote>
<ul>
<li><strong>get_data</strong></li>
</ul>
<blockquote>
<p>用于获取指定设备名中的变量值。操作方法为(data_store为实例):</p>
<p><code>data_store.get_data(<device_name>, <variable_name>)</code></p>
</blockquote>
<h3>全局常量</h3>
<blockquote>
<p>全局常量是指在指令字典文件中,<code>Constants</code>属性块内定义的常量。这些常量可以在指令参数、操作项参数等地方通过<code>{constant_name}</code>的方式引用,方便在多个地方使用同一个值,并且只需要修改一处即可。</p>
<p>常量的命名格式为全大写字母和下划线的组合,例如<code>AP_NAME</code>、<code>AP_PASSWORD</code>等。使用时需要确保常量名称与定义时一致,并且在引用时使用花括号包裹起来。</p>
<p>ℹ 当常量中没有给定相对应的值的时候,在你执行字典文件时会提示你输入该常量的值,输入完成后会自动替换指令参数中的相应常量引用,并且将你输入的值存储到临时数据中,供后续指令参数调用。</p>
</blockquote>
<h4>全局常量使用方法</h4>
<p><code>Constants</code>属性块与<code>Commands</code>和<code>Devices</code>等属性块是平级的,位于指令字典文件的根层级。你可以在<code>Constants</code>中定义任意数量的常量,例如:</p>
<pre lang="json"><code>{
    "Constants": {
        "DeviceA_PORT": "COM14",
        "AP_NAME": "MyAccessPoint",
        "AP_PASSWORD": "SecurePass123",
        "Target_SSID": "TargetNetwork",
        "Target_PASSWORD": "targetpass456"
    },
    "Devices": [...],
    "Commands": [...]
}

在上面的例子中,我们定义了四个常量:AP_NAMEAP_PASSWORDTarget_SSIDTarget_PASSWORD。你可以在指令参数中通过{AP_NAME}{AP_PASSWORD}等方式引用这些常量,例如:

{
    "command": "AT+SOFTAP=\"{AP_NAME}\",\"{AP_PASSWORD}\"",
    "expected_responses": [
        "OK"
    ],
    "device": "DeviceA",
    "order": 1,
    "parameters": [],
    "timeout": 3000,
    "success_actions": [
        {
            "wifi_connect": {
                "ssid": "{AP_NAME}",
                "password": "{AP_PASSWORD}",
                "timeout": 20
            }
        }
    ]
}

当然,你也可以在执行字典中各个地方穿插全局常量的引用,你甚至可以在Devices属性块中引用全局常量,例如:

{
    "Constants": {
        "DeviceA_PORT": "COM14",
        "AP_NAME": "MyAccessPoint",
        "AP_PASSWORD": "SecurePass123"
    },
    "Devices": [
        {
            "name": "DeviceA",
            "status": "enabled",
            "port": "{DeviceA_PORT}",
            "baud_rate": 115200,
            "stop_bits": 1,
            "parity": null,
            "data_bits": 8,
            "flow_control": {
                "xon_xoff": false,
                "rts_cts": false,
                "dsr_dtr": false
            },
            "dtr": false,
            "rts": false
        }
    ],
    "Commands": [
        {
            "command": "AT+SOFTAP=\"{AP_NAME}\",\"{AP_PASSWORD}\"",
            "expected_responses": [
                "OK"
            ],
            "device": "DeviceA",
            "order": 1,
            "parameters": [],
            "timeout": 3000,
            "success_actions": [
                {
                    "wifi_connect": {
                        "ssid": "{AP_NAME}",
                        "password": "{AP_PASSWORD}",
                        "timeout": 20
                    }
                }
            ]
        }
    ]
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autocom-1.1.0.tar.gz (59.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autocom-1.1.0-py3-none-any.whl (63.9 kB view details)

Uploaded Python 3

File details

Details for the file autocom-1.1.0.tar.gz.

File metadata

  • Download URL: autocom-1.1.0.tar.gz
  • Upload date:
  • Size: 59.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.13

File hashes

Hashes for autocom-1.1.0.tar.gz
Algorithm Hash digest
SHA256 b46cebeb662694c1d0f4b3dc8f0e8fe87424ae66889bb31aaf5eb91333e3039c
MD5 de9532919b939503872a99e43a433942
BLAKE2b-256 eef949dc0cd0879435f49b87f62722f4675b72123460d6c4b5fd1f4fb5cf7081

See more details on using hashes here.

File details

Details for the file autocom-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: autocom-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 63.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.13

File hashes

Hashes for autocom-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4423476514bd6a2dfd34af70a5562d1760bc81c1e19e36f53c76fccfc3b4e6cd
MD5 a41c653363063bbf1200e12bd60e2dd0
BLAKE2b-256 bfe214eb274611ad8a43ffb6755c4de4cffc1d94a5fd1ff874d6ea2e84a07aaa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page