Ethernet/IP是一種工業(yè)自動化領(lǐng)域中常用的網(wǎng)絡(luò)通信協(xié)議,它是基于標(biāo)準(zhǔn)以太網(wǎng)技術(shù)的應(yīng)用層協(xié)議。作為工業(yè)領(lǐng)域的通信協(xié)議之一,Ethernet/IP 提供了一種在工業(yè)自動化設(shè)備之間實(shí)現(xiàn)通信和數(shù)據(jù)交換的標(biāo)準(zhǔn)化方法。python要實(shí)現(xiàn)Ethernet/IP的客戶端,可以采用pycomm3模塊,但不一定是pycomm3,其中原委咋們慢慢聊,本文為第三篇。
一、關(guān)于CIPDriver模塊
1、官方例子
Generic Messaging - pycomm3 1.2.14 documentation
在官方例子中,出現(xiàn)率最高的方法是 generic_message ,我們再去看看他的API。
2、API
CIPDriver API - pycomm3 1.2.14 documentation
在這個文檔中,我們驚訝地發(fā)現(xiàn)他的主要方法也只是generic_message,這讓人感覺不太可能實(shí)現(xiàn)第一篇文章的交互。
3、還是先用吧
明知這個類大概率實(shí)現(xiàn)不了,為什么還要繼續(xù)呢?
我們在實(shí)現(xiàn)一個協(xié)議時,最起碼先了解這個協(xié)議吧?在第一篇文章中,我們了解的情況是閱讀了一些官方文檔,也了解了EDS文件,但沒有一個具體的實(shí)驗(yàn)。因此,繼續(xù)是有必要的,至少能了解協(xié)議本身。
4、generic_message方法
對于官方例子,我們先結(jié)合源碼描述簡單分析:
(1)源碼描述
def generic_message(
self,
service: Union[int, bytes],
class_code: Union[int, bytes],
instance: Union[int, bytes],
attribute: Union[int, bytes] = b"",
request_data: Any = b"",
data_type: Optional[Union[Type[DataType], DataType]] = None,
name: str = "generic",
connected: bool = True,
unconnected_send: bool = False,
route_path: Union[bool, Sequence[CIPSegment], bytes, str] = True,
**kwargs,
) -> Tag:
"""
Perform a generic CIP message. Similar to how MSG instructions work in Logix.
:param service: service code for the request (single byte)
:param class_code: request object class ID
:param instance: ID for an instance of the class
If set with 0, request class attributes.
:param attribute: (optional) attribute ID for the service/class/instance
:param request_data: (optional) any additional data required for the request.
:param data_type: a ``DataType`` class that will be used to decode the response, None to return just bytes
:param name: return ``Tag.tag`` value, arbitrary but can be used for tracking returned Tags
:param connected: ``True`` if service required a CIP connection (forward open), ``False`` to use UCMM
:param unconnected_send: (Unconnected Only) wrap service in an UnconnectedSend service
:param route_path: (Unconnected Only) ``True`` to use current connection route to destination, ``False`` to ignore,
Or provide a path string, list of segments to be encoded as a PADDED_EPATH, or
an already encoded path.
:return: a Tag with the result of the request. (Tag.value for writes will be the request_data)
"""
(2)簡單分析
官方文檔直接給了一個函數(shù),我做了一些引入的補(bǔ)充,即“from pycomm3 import CIPDriver, Services, INT” :
from pycomm3 import CIPDriver, Services, INT
def read_pf525_parameter():
drive_path = '10.10.10.100/bp/1/enet/192.168.1.55'
with CIPDriver(drive_path) as drive:
param = drive.generic_message(
service=Services.get_attribute_single,
class_code=b'x93',
instance=41, # Parameter 41 = Accel Time
attribute=b'x09',
data_type=INT,
connected=False,
unconnected_send=True,
route_path=True,
name='pf525_param'
)
print(param)
對于? ? drive_path = '10.10.10.100/bp/1/enet/192.168.1.55' 這個語句,再結(jié)合上次的實(shí)驗(yàn),我猜測EIP設(shè)備是10.10.10.100,并且該EIP設(shè)備是有一些子模塊的,192.168.1.55便是內(nèi)部的子模塊地址。中間的/bp/1/enet則是按照EIP協(xié)議規(guī)定的路徑。
在使用 with
語句創(chuàng)建了一個 CIPDriver
的實(shí)例(即自動調(diào)用了open()方法),確保在代碼塊結(jié)束時正確關(guān)閉連接后,接著調(diào)用了generic_message方法發(fā)送了一個通用的消息。具體參數(shù)如下:
service=Services.get_attribute_single
: 使用 EtherNet/IP 協(xié)議中的get_attribute_single
服務(wù)。class_code=b'x93'
: 類別代碼,可能是特定設(shè)備或?qū)ο箢愋偷臉?biāo)識。instance=41
: 代表要訪問的具體實(shí)例,這里是 Parameter 41。attribute=b'x09'
: 屬性標(biāo)識,可能代表具體要獲取的信息的類型。data_type=INT
: 數(shù)據(jù)類型,這里是整數(shù)。connected=False
: 表示使用不連接的方式發(fā)送消息。unconnected_send=True
: 允許未連接發(fā)送,可能用于廣播或多播。route_path=True
: 表示要使用路由路徑(如果需要)。name='pf525_param'
: 為此消息指定了一個名稱,這個名稱在返回的結(jié)果中可以用于標(biāo)識。
好了,通過上述解釋其實(shí)還有很多不理解的地方,我們繼續(xù)實(shí)驗(yàn)來進(jìn)一步了解。
二、繼續(xù)實(shí)驗(yàn)
1、請求看看
修改代碼讓其請求成功,提示如下:
pf525_param, None, INT, IOI syntax error. A syntax error was detected decoding the Request Path (see extended status) - Extended status out of memory ?(04, 00)
表明沒有異常,只是服務(wù)器沒有這些擴(kuò)展?fàn)顟B(tài),說明我們請求的資源不存在。
from pycomm3 import CIPDriver, Services, INT
def read_pf525_parameter():
drive_path = '192.168.1.189'
with CIPDriver(drive_path) as drive:
param = drive.generic_message(
service=Services.get_attribute_single,
class_code=b'x93',
instance=41,
attribute=b'x09',
data_type=INT,
connected=False,
unconnected_send=True,
route_path=True,
name='pf525_param'
)
print(param)
read_pf525_parameter()
查看了報(bào)文依舊在報(bào)路徑錯誤。
我們對比一下正常的請求,我們的請求缺失了請求服務(wù)列表這一步,打開路徑時是以不連接進(jìn)行打開的,因此差異很大。
2、怎么辦呢
莫慌,問題總會得到解決的,而且現(xiàn)在我們的思路很清晰,即我們的請求有問題,下一步就是不斷實(shí)驗(yàn)就好?,F(xiàn)在我們應(yīng)該具備一系列的進(jìn)行實(shí)驗(yàn)的素質(zhì),這些素質(zhì)有助于確保實(shí)驗(yàn)的成功進(jìn)行并獲得可靠的結(jié)果。以下是一些進(jìn)行實(shí)驗(yàn)時應(yīng)具備的素質(zhì):
好奇心: 具備對未知事物的好奇心,愿意去探索和發(fā)現(xiàn)新知識。
耐心: 實(shí)驗(yàn)過程中可能需要耐心等待結(jié)果或進(jìn)行多次試驗(yàn),特別是在研究型實(shí)驗(yàn)中。
精確性: 具備準(zhǔn)確記錄實(shí)驗(yàn)數(shù)據(jù)的能力,以確保實(shí)驗(yàn)結(jié)果的可信度。
邏輯思維: 能夠理清實(shí)驗(yàn)的步驟和邏輯,分析實(shí)驗(yàn)結(jié)果并得出結(jié)論。
實(shí)驗(yàn)設(shè)計(jì)能力: 能夠設(shè)計(jì)合理的實(shí)驗(yàn)方案,考慮到實(shí)驗(yàn)的目的、變量和控制措施。
安全意識: 遵守實(shí)驗(yàn)室安全規(guī)定,正確使用實(shí)驗(yàn)設(shè)備,確保實(shí)驗(yàn)過程中的安全。
團(tuán)隊(duì)合作: 在團(tuán)隊(duì)中合作順利,有時實(shí)驗(yàn)需要多人協(xié)作完成。
問題解決能力: 遇到實(shí)驗(yàn)中的問題時能夠迅速分析并找到解決方案。
記錄與報(bào)告: 能夠準(zhǔn)確地記錄實(shí)驗(yàn)步驟和結(jié)果,并能夠撰寫清晰的實(shí)驗(yàn)報(bào)告。
批判性思維: 能夠?qū)徤髟u估實(shí)驗(yàn)的方法和結(jié)果,對實(shí)驗(yàn)中的偏差和誤差有清晰的認(rèn)識。
耐受失?。?/strong> 實(shí)驗(yàn)中可能會遇到失敗或意外,具備面對挫折的耐受力。
道德責(zé)任感: 遵守科學(xué)研究的倫理規(guī)范,保護(hù)實(shí)驗(yàn)對象和參與者的權(quán)益。
這些素質(zhì)有助于建立一個科學(xué)、安全、可靠的實(shí)驗(yàn)環(huán)境,確保實(shí)驗(yàn)的有效進(jìn)行和獲得有意義的結(jié)果。