Skip to main content

用于与 Allen-Bradley PLC 通信的 Python 以太网/IP 库。

项目描述

PyPI 版本 执照 Python 版本

下载 观察者 星星 叉子

阅读文档 表情符号

介绍

pycomm3最初是pycomm的 Python 3 分支,它是一个 Python 2 库,用于使用以太网/IP 与 Allen-Bradley PLC 进行通信。最初的 Python 3 移植是在这个fork中完成的,并被用作pycomm3的基础。从那时起,该库几乎被完全重写,API 不再与pycomm兼容。如果没有原始pycomm开发人员的辛勤工作, pycomm3就不会存在。这个图书馆试图扩展他们的伟大工作。

驱动程序

pycomm3包括 3 个驱动程序:

  • CIP驱动程序

    此驱动程序是库的基本驱动程序,它处理其他驱动程序使用的常见 CIP 服务。诸如打开/关闭连接、注册/注销会话、转发打开/关闭服务、设备发现和通用消息传递之类的事情。它可用于连接任何以太网/IP 设备,例如:驱动器、交换机、仪表和其他非 PLC 设备。

  • 逻辑驱动程序

    此驱动程序支持特定于 ControlLogix、CompactLogix 和 Micro800 PLC 的服务。读取/写入标签、上传标签列表、获取/设置 PLC 时间等服务。

  • SLC驱动程序

    该驱动程序支持 SLC500 或 MicroLogix PLC 中的基本读/写数据文件。它是来自pycomm的SlcDriver的一个端口,只需稍加改动即可使 API 与其他驱动程序相似。目前,该驱动程序被认为是遗留的,它的开发将在有限的基础上进行。

免责声明

PLC 可用于控制重型或危险设备,该库按“原样”提供,不保证其在生产环境中的可靠性。该库不承诺协议实现的完整性或正确性,不应仅依赖于关键系统。该库的开发旨在为 Allen-Bradley PLC 内的读取/写入数据提供快速便捷的访问。

设置

可以使用pip从PyPI安装该软件包:pip install pycomm3python -m pip install pycomm3

或者,您可以使用 Python 标准日志记录库配置日志记录。提供了一种方便的方法来帮助配置基本日志记录,请参阅文档中的日志记录部分以获取更多信息。

Python 和操作系统支持

pycomm3是一个仅限 Python 3 的库,支持从 3.6.1 到 3.10 的 Python 版本。应该没有特定于操作系统的要求,并且应该能够在任何支持 Python 的操作系统上运行。开发和测试主要在 Windows 10 上完成。如果您遇到与操作系统相关的问题,请在GitHub 存储库中打开一个问题,我们将对其进行调查。

文档

本 README 涵盖了该库的基本概述,完整的文档可以在 Read the Docs或访问https://pycomm3.dev中找到。

贡献

如果您想贡献或遇到问题,请阅读贡献指南。

突出特点

  • generic_message用于未直接实现的额外功能
    • 工作方式类似于 Logix 中的 MSG 指令,参数类似于 MESSAGE 属性

    • 有关获取/设置驱动器参数、IP 配置或上传 EDS 文件等内容,请参阅示例部分

    • 在内部用于实现其他一些方法(get/set_plc_time、前向打开/关闭等)

  • 简化数据类型
    • 通过从用户那里抽象出 CIP 实现细节,允许使用标准 Python 类型

    • 字符串使用普通的 Python str对象,不需要分别处理LENDATA属性

    • 自定义字符串类型也会自动识别,不仅限于内置的

    • BOOL 数组使用普通的 Python bool对象,不需要对 DWORD 值进行复杂的位移

    • 强大的类型系统,允许类型表示任何 CIP 对象并处理对象的编码/解码

逻辑驱动程序

  • 简单的 API,标签只有 1种读取方法和 1种写入方法。
    • 不需要对不同的数据类型使用不同的方法

    • 只需要标签名称,不需要用户提供其他信息

    • 自动管理请求/响应大小以将尽可能多的请求打包到单个数据包中

    • 自动处理无法放入单个数据包的大型标签的碎片请求

    • 两者都支持完整的结构读/写(UDT、AOI 等)
      • 用于读取Tag.value将是{ attribute: value}字典

      • 写入值应该是 {attribute: value} 的字典根据需要嵌套
        • 不做部分写入,值必须匹配完整的结构

        • 不推荐用于内置类型(TIMER、CONTROL、COUNTER 等)

      • 两者都不需要任何属性才能具有 None 的外部访问权限

  • 从 PLC 上传标签列表和数据类型定义
    • 无需用户确定可用的标签(如从 L5X 导出)

    • /方法需要定义

  • 根据目标 PLC 自动启用/禁用不同的功能
    • 扩展前向开放(EN2T 或更新版本和 v20+)

    • 符号实例寻址 (Logix v21+)

    • 检测 Micro800 并禁用不支持的功能(CIP 路径、前向打开、实例寻址等)

LogixDriver 概述

创建驱动程序很简单,只需要一个路径参数。路径可以是 IP 地址、IP 和插槽,或完整的CIP 路由,有关详细信息,请参阅文档。下面的示例显示了如何创建一个简单的驱动程序并打印收集到的有关设备的一些信息。

from pycomm3 import LogixDriver

with LogixDriver('10.20.30.100/1') as plc:
    print(plc)
    # OUTPUT:
    # Program Name: PLCA, Device: 1756-L83E/B, Revision: 28.13

    print(plc.info)
    # OUTPUT:
    # {'vendor': 'Rockwell Automation/Allen-Bradley', 'product_type': 'Programmable Logic Controller',
    #  'product_code': 166, 'version_major': 28, 'version_minor': 13, 'revision': '28.13', 'serial': 'FFFFFFFF',
    #  'device_type': '1756-L83E/B', 'keyswitch': 'REMOTE RUN', 'name': 'PLCA'}

读/写标签

读取或写入标签就像调用readwrite方法一样简单。这两种方法都接受任意数量的标签,并会自动将多个标签打包到多服务包服务 (0x0A)中,同时确保保持在连接大小以下。如果有标签值不适合请求/回复数据包,它将使用Read Tag Fragmented (0x52)Write Tag Fragmented (0x53)请求自动处理该标签。

两种方法都会返回Tag对象来反映操作的成功或失败。

class Tag(NamedTuple):
    tag: str  # the name of the tag, does not include ``{<# elements>}`` from request
    value: Any  # value read or written, may be ``None`` if an error occurred
    type: Optional[str] = None  # data type of tag, including ``[<# elements>]`` from request
    error: Optional[str] = None  # ``None`` if successful, else the CIP error or exception thrown

如果值不是None并且错误None ,则标记对象被认为是成功的(真实的)。

例子:

with LogixDriver('10.20.30.100') as plc:
    plc.read('tag1', 'tag2', 'tag3')  # read multiple tags
    plc.read('array{10}') # read 10 elements starting at 0 from an array
    plc.read('array[5]{20}) # read 20 elements starting at elements 5 from an array
    plc.read('string_tag')  # read a string tag and get a string
    plc.read('a_udt_tag') # the response .value will be a dict like: {'attr1`: 1, 'attr2': 'a string', ...}

    # writes require a sequence of tuples of [(tag name, value), ... ]
    plc.write('tag1', 0)  # single writes do not need to be passed as a tuple
    plc.write(('tag1', 0), ('tag2', 1), ('tag3', 2))  # write multiple tags
    plc.write(('array{5}', [1, 2, 3, 4, 5]))  # write 5 elements to an array starting at the 0 element
    plc.write('array[10]{5}', [1, 2, 3, 4, 5])  # write 5 elements to an array starting at element 10
    plc.write('string_tag', 'Hello World!')  # write to a string tag with a string
    plc.write('string_array[2]{5}', 'Write an array of strings'.split())  # write an array of 5 strings starting at element 2
    plc.write('a_udt_tag', {'attr1': 1, 'attr2': 'a string', ...})  # can also use a dict to write a struct

    # Check the results
    results = plc.read('tag1', 'tag2', 'tag3')
    if all(results):
        print('They all worked!')
    else:
        for result in results:
            if not result:
                print(f'Reading tag {result.tag} failed with error: {result.error}')

单元测试

pytest用于单元测试。tests目录包含测试程序的 L5X 导出,其中包含测试所需的所有标签。测试的唯一要求(除了带有测试程序的正在运行的 PLC)是定义的 PLC 的环境变量PLCPATH

用户测试

这些测试供用户运行。有一些特定于演示 plc 的测试,不包括在内。要运行它们,您有以下选项:

毒物

  • 修改tox.ini中的PLCPATH变量

  • 然后运行这个命令:tox -e user

或使用pytest

set PLCPATH=192.168.1.100
pytest --ignore tests/online/test_demo_plc.py

(或你的shell中的等价物)

执照

pycomm3在 MIT 许可证下分发