omron fins 内存区域写入(MEMORY AREA WRITE)

1. 完整的代码如下:

import socket
import binascii


class Omron:
    def __init__(self, ip, port=9600):
        self.ip = ip  # PLC的IP地址
        self.port = port  # PLC的端口,默认为9600

    def send_receive_fins(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sc:
            sc.settimeout(30)  # 设置socket超时时间为30秒
            try:
                sc.connect((self.ip, self.port))  # 尝试连接到PLC
                sc.send(binascii.unhexlify('46494e530000000c000000000000000000000000'))  # 发送初始化包
                response = sc.recv(4096)  # 接收PLC的响应

                if binascii.hexlify(response)[:4] != b'4649':  # 检查响应是否以'FINS'开始
                    return False

                # 第一部分:FINS/TCP Header 字段信息
                magic_bytes = "46494e53"  # FINS, 4个字节

                # 修改:需要根据写入数据的长度来设置长度字段
                length = "0000002c"  # length以后所有字段的长度,4个字节
                # 修改:需要根据写入数据的长度来设置长度字段

                command = "00000002"  # 发送帧,4个字节
                error_code = "00000000"  # 错误码,4个字节

                # 第二部分:FINS Header 字段信息
                information_control_field = "80"  # 信息控制字段,1个字节
                reserved = "00"  # 保留,1个字节
                gateway_count = "02"  # 网关数
                destination_network_address = "00"  # 目标网络地址,1个字节
                destination_node_number = self.extract(response, 46)  # 提取PLC返回的server_node_address
                destination_unit_address = "00"  # 目标单元地址,1个字节
                source_network_address = "00"  # 源网络地址,1个字节
                source_node_number = "00"  # 源节点地址,1个字节
                source_unit_address = "ef"  # 源单元地址,1个字节

                # 修改部分
                service_id = "00"  # 服务ID,此处为00,表示读取数据,1个字节
                command_code = "0102"  # 命令代码,此处为内存区域写入,2个字节
                memory_area_code = "82"  # 内存区域代码,1个字节,此处为82,表示为PLC的DM区域
                beginning_address = "006400"  # 起始地址,3个字节,此处为0x6400
                item_count = "0009"  # 写9个字的数据,2个字节,一个字为2个字节
                data = "617164627432707737396d306964746b3833"  # 待写入的数据,# len(data) = item_count * 2 = 18字节
                # 修改部分

                cmd_packet = magic_bytes + \
                             length + \
                             command + \
                             error_code + \
                             information_control_field + \
                             reserved + \
                             gateway_count + \
                             destination_network_address + \
                             destination_node_number + \
                             destination_unit_address + \
                             source_network_address + \
                             source_node_number + \
                             source_unit_address + \
                             service_id + \
                             command_code + \
                             memory_area_code + \
                             beginning_address + \
                             item_count + \
                             data

                print('cmd_packet:', binascii.unhexlify(cmd_packet))
                sc.send(binascii.unhexlify(cmd_packet))  # 发送指令包
                response = sc.recv(1024)  # 接收PLC的响应
            except Exception as e:
                print(f"连接或传输错误: {e}")  # 输出错误信息
                return False

    @staticmethod
    def extract(data, offset):
        hex_data = binascii.hexlify(data).decode()  # 将数据转换为十六进制字符串
        return hex_data[offset:offset + 2]  # 返回指定位置的数据


if __name__ == '__main__':
    omron_plc = Omron('89.186.98.168', 9600)  # 实例化Omron类,设置IP和端口
    print(omron_plc.send_receive_fins())  # 发送请求并打印返回的PLC信息

2. 需要修改的字段包括:length、service_id、 command_code、memory_area_code、 beginning_address 、item_count、data,具体如下:
length = TCP length - 8 = 24 + item_count的字节数 + item_count (十进制)* 2

length = "0000002c" 
command = "00000002"  # 4个字节
error_code = "00000000"  # 4个字节

# 第二部分:FINS Header 字段信息
information_control_field = "80"  # 1个字节
reserved = "00" # 1个字节
gateway_count = "02"  # 1个字节
destination_network_address = "00"  # 1个字节
destination_node_number = self.extract(response, 46)  # 1个字节
destination_unit_address = "00"  # 1个字节
source_network_address = "00"  # 1个字节
source_node_number = "00"  # 1个字节
source_unit_address = "ef"  # 1个字节

# 修改部分
service_id = "00"  # 1个字节
command_code = "0102"  # 2个字节
memory_area_code = "82"  # 1个字节
beginning_address = "006400"  # 3个字节
item_count = "0009"  # 2个字节,写9个字的数据,一个字为2个字节
data = "617164627432707737396d306964746b3833"  # len(data) = item_count * 2 = 18字节

3. 捕获的数据包如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值