各位大大好, 小弟目前需要使用python讀取/控制 Omron PLC,
在讀取的時候,都正常能夠取到值,
但在寫入的時候出現以下狀況:
修改點位(D0001)為100,數值確實有變動,但是點位(D0002、D0003)同時被更改為0
補充: 我目前在python利用ctype轉換型態,再利用pythonnet呼叫C#的開源庫,將數值傳送至C#的函式。
// C#的實現方法如下
// omronConn的部份為開源庫提供函式
// 已知以下的代碼能夠正常寫入
// ...
double double_value = short.Parse(value);
omronConn.Write(recipe, double_value);
# Python的實現方法如下
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Python 3.7
# pip install pythonnet
# DLL 為 C#
import ctypes
import re
import sys
import clr
try:
    HSL = clr.AddReference(
        r"src\modules\OmronSDK\omron\lib\net451\HslCommunication"
    )
    hsl_location = HSL.Location
    SYSTEM = clr.AddReference(
        "System"
    )
    system_location = SYSTEM.Location
    print("\n")
    print("Load library %s" % hsl_location)
    print("Load library %s" % system_location)
    print("\n")
except Exception:
    raise
class OmronSDK:
    from HslCommunication.Profinet.Omron import OmronFinsNet
    from System import Convert, Int32
    def __init__(self, local_ip: str, plc_ip: str, plc_port: int = 9600) -> None:
        self.local_ip = local_ip
        self.plc_ip = plc_ip
        self.plc_port = plc_port
        self.conn = None
    @classmethod
    def Valid_IPv4_Address(self, ip) -> bool:
        """Valid_IPv4_Address IP驗證
        Args:
            ip (_type_): IP Address
        Returns:
            bool: True or False
        """
        m = re.match(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ip)
        return bool(m) and all(map(lambda n: 0 <= int(n) <= 255, m.groups()))
    def Connect(self) -> tuple:
        """Connect
        Raises:
            ValueError: IP 輸入錯誤
        Returns:
            tuple: 返回結果
        """
        self.suffix_local_ip = ""
        self.suffix_plc_ip = ""
        try:
            if self.Valid_IPv4_Address(self.local_ip) and \
                    self.Valid_IPv4_Address(self.plc_ip):
                self.suffix_local_ip = self.local_ip.split(".")[-1]
                self.suffix_plc_ip = self.plc_ip.split(".")[-1]
            else:
                raise ValueError("Input IP type error !!!")
        except Exception:
            raise
        try:
            if self.conn is None:
                omron = OmronSDK.OmronFinsNet(
                    self.plc_ip,
                    OmronSDK.Int32(self.plc_port)
                )
                # Server IP 後綴尾碼
                omron.SA1 = OmronSDK.Convert.ToByte(self.suffix_local_ip)
                # PLC IP 後綴尾碼
                omron.DA1 = OmronSDK.Convert.ToByte(self.suffix_plc_ip)
                # 固定為0
                omron.DA2 = 0x00
                result = omron.ConnectServer()
            if result is None:
                return (result, "Omron connection faild.")
            elif not result.IsSuccess:
                return (None, result.Message)
            elif result.IsSuccess:
                self.conn = omron
                return (result.Message, "CNC connection successfully.")
        except Exception as err_msg:
            raise
    def Disconnect(self) -> object:
        """Disconnect
        Returns:
            object: 返回結果
        """
        return self.conn.ConnectClose()
    def Reader(self, typer: str, recipe: str) -> tuple:
        try:
            typer = typer.upper()
            value = ""
            if typer == "BOOL":
                value = self.conn.ReadBool(recipe).Content
            elif typer == "SHORT":
                value = self.conn.ReadInt16(recipe).Content
            elif typer == "USHORT":
                value = self.conn.ReadUInt16(recipe).Content
            elif typer == "INT":
                value = self.conn.ReadInt32(recipe).Content
            elif typer == "UINT":
                value = self.conn.ReadUInt32(recipe).Content
            elif typer == "FLOAT":
                value = self.conn.ReadFloat(recipe).Content
            elif typer == "LONG":
                value = self.conn.ReadInt64(recipe).Content
            elif typer == "ULONG":
                value = self.conn.ReadUInt64(recipe).Content
            elif typer == "DOUBLE":
                value = self.conn.ReadDouble(recipe).Content
            elif typer == "STRING":
                # ASCII
                value = self.conn.ReadString(recipe, 5).Content
            return (typer, value)
        except Exception:
            raise
    def Writer(self, typer: str, recipe: str, value):
        # 此部分能夠正常更改數值,但會有多個點位被同時更改的問題,且都為0
        try:
            typer = typer.upper()
            if typer == "BYTES":
                self.conn.Write(recipe, str.encode(value))
            elif typer == "SHORT":
                self.conn.Write(recipe, (ctypes.c_ushort(int(value))).value)
            elif typer == "FLOAT":
                self.conn.Write(recipe, ctypes.c_float(float(value)))
            elif typer == "LONG":
                self.conn.Write(recipe, ctypes.c_long(int(value)))
            elif typer == "ULONG":
                self.conn.Write(recipe, ctypes.c_ulong(int(value)))
            elif typer == "DOUBLE":
                self.conn.Write(recipe, ctypes.c_double(float(value)).value)
            elif typer == "STRING":
                # ASCII
                self.conn.Write(recipe, str(value))
        except Exception as err_msg:
            pass
def Testing():
    import datetime
    import logging
    import os
    import platform
    from ctypes import byref, windll, wintypes
    while True:
        try:
            print("----- Press [quit(q)]/[Ctrl-c] to exit -----")
            print("\n")
            plc_ip = '10.30.99.199'
            plc_port = '9600'
            local_ip = '10.30.99.21'
            if not OmronSDK.Valid_IPv4_Address(plc_ip) and \
                    not OmronSDK.Valid_IPv4_Address(local_ip):
                continue
            if plc_ip == "q" or plc_ip == "quit":
                sys.exit(0)
            omron = OmronSDK(
                local_ip=local_ip,
                plc_ip=plc_ip,
                plc_port=plc_port
            )
            conn = omron.Connect()
            use_function = input("Select function w or r: ")
            if use_function == 'w':
                while True and conn[0] == '成功':
                    try:
                        print("\n")
                        typer = input(
                            "Input recipe type [BYTES SHORT USHORT UINT FLOAT LONG ULONG DOUBLE STRING]: ")
                        recipe = input("Input recipe code: ")
                        recipe_value = input("Input recipe value: ")
                        if typer == "q" or recipe == "quit":
                            sys.exit(0)
                        writer = omron.Writer(
                            typer=typer,
                            recipe=recipe,
                            value=recipe_value
                        )
                        logger.info(writer)
                    except KeyboardInterrupt:
                        break
                    except Exception:
                        raise
            if use_function == 'r':
                while True and conn[0] == '成功':
                    try:
                        print("\n")
                        typer = input(
                            "Input recipe type [BOOL SHORT USHORT INT UINT FLOAT LONG ULONG DOUBLE STRING]: ")
                        recipe = input("Input recipe code: ")
                        if typer == "q" or recipe == "quit":
                            sys.exit(0)
                        reader = omron.Reader(
                            typer=typer,
                            recipe=recipe
                        )
                        logger.info(reader)
                    except KeyboardInterrupt:
                        break
                    except Exception:
                        raise
        except KeyboardInterrupt:
            omron.Disconnect()
            sys.exit(0)
        except Exception:
            raise
if __name__ == "__main__":
    Testing()
小弟目前在懷疑是否是轉換時型態有誤...
試了很久,網上也不太有資料...
請各位大大指點一些道路,小弟感激不盡。