加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 三、關(guān)于MC協(xié)議的整體實(shí)現(xiàn)
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

python實(shí)現(xiàn)MC協(xié)議(SLMP 3E幀)的TCP服務(wù)端(篇二)

12/08 08:05
1042
閱讀需 16 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

python實(shí)現(xiàn)MC協(xié)議(SLMP 3E幀)的TCP服務(wù)端是一件稍微麻煩點(diǎn)的事情。它不像modbusTCP那樣,可以使用現(xiàn)成的pymodbus模塊去實(shí)現(xiàn)。但是,我們可以根據(jù)協(xié)議幀進(jìn)行組包,自己去實(shí)現(xiàn)幀的格式,而這一切可以基于socket模塊。本文為第二篇。

二、讀寫保持寄存器的完整交互包

# 客戶端發(fā)送(讀) -》
50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 00 00 00 A8 05 00
# 《- 服務(wù)端應(yīng)答
D0 00 00 FF FF 03 00 0C 00 00 00 73 00 00 00 00 00 00 00 00 00
# 客戶端發(fā)送(寫) -》
50 00 00 FF FF 03 00 16 00 10 00 01 14 00 00 0A 00 00 A8 05 00 4E 47 00 00 00 00 00 00 00 00
# 《- 服務(wù)端應(yīng)答
D0 00 00 FF FF 03 00 02 00 00 00

1、分析交互包

基于上述交互包,我們查閱官方文檔發(fā)現(xiàn)交互包使用的是二進(jìn)制代碼。那么,二進(jìn)制代碼與ASCII代碼有什么區(qū)別呢?

SLMP(Seamless Message Protocol)3E幀有兩種表示方式:二進(jìn)制格式和ASCII格式。它們的區(qū)別在于數(shù)據(jù)的傳輸方式和呈現(xiàn)形式。

(1)二進(jìn)制格式

在二進(jìn)制格式中,SLMP 3E幀中的各個(gè)字段(如幀頭、副幀頭、命令碼、數(shù)據(jù)等)以二進(jìn)制形式直接編碼和傳輸。數(shù)據(jù)在網(wǎng)絡(luò)中以原始的二進(jìn)制位模式傳輸,這種方式效率較高,適用于網(wǎng)絡(luò)傳輸。二進(jìn)制格式通常用于實(shí)際的網(wǎng)絡(luò)通信中,數(shù)據(jù)以二進(jìn)制流的形式在網(wǎng)絡(luò)上傳輸。

(2)ASCII格式

在ASCII格式中,SLMP 3E幀中的各個(gè)字段被轉(zhuǎn)換成ASCII字符表示。數(shù)據(jù)以ASCII碼的文本形式進(jìn)行傳輸,每個(gè)字節(jié)被轉(zhuǎn)換為兩個(gè)ASCII字符(通常是十六進(jìn)制表示)。ASCII格式通常用于調(diào)試和人機(jī)界面中,方便人們查看和理解數(shù)據(jù)。

總的來說,二進(jìn)制格式適用于機(jī)器之間的網(wǎng)絡(luò)通信,而ASCII格式適用于人機(jī)交互和調(diào)試過程中的數(shù)據(jù)顯示。選擇哪種格式取決于具體的應(yīng)用場(chǎng)景和需求。

因此,本文實(shí)現(xiàn)的是二進(jìn)制格式,如果你會(huì)實(shí)現(xiàn)二進(jìn)制格式,那么你也能實(shí)現(xiàn)ASCII格式。

2、讀寫保持寄存器的請(qǐng)求處理

(1)表頭

客戶端的兩個(gè)請(qǐng)求,相同部分都為50 00 00 FF FF 03 00,我們姑且稱之為表頭。

(2)讀/寫長度(協(xié)議幀的長度)

0C 00是固定長度(讀的時(shí)候報(bào)文都是這么長)與16 00 根據(jù)實(shí)際長度變化,表示后面數(shù)據(jù)的長度,例如前者,應(yīng)該以00 0C來看長度,表示后面有12個(gè)00那樣的長度。

(3)固定值

10 00

(4)讀/寫指令

01 04 / 01 14

(5)讀/寫寄存器地址

00 00 00 00 00 A8 05 00 /??00 00 0A 00 00 A8 05 00,其中寫的0A 00代表從第10個(gè)保持寄存器,05表示讀寫5個(gè)寄存器

3、讀寫保持寄存器的響應(yīng)處理

(1)表頭

客戶端的兩個(gè)請(qǐng)求,相同部分都為D0 00 00 FF FF 03 00,我們姑且稱之為表頭。

(2)長度(協(xié)議幀的長度)

讀:0C 00根據(jù)實(shí)際長度變化,寫:02 00 可以不變化。

(3)固定值

00 00

(4)讀/寫響應(yīng)

響應(yīng)實(shí)際讀到的數(shù)據(jù)?/ 無

4、程序設(shè)計(jì)

根據(jù)上述內(nèi)容,實(shí)現(xiàn)了一個(gè)定制MC服務(wù)器,能夠處理保持寄存器的讀寫請(qǐng)求,給出正確的響應(yīng)。

import socket
import struct

# 創(chuàng)建一個(gè)TCP/IP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定套接字到特定地址和端口
server_address = ('192.168.1.188', 12345)  # 服務(wù)器地址和端口
server_socket.bind(server_address)

# 監(jiān)聽連接
server_socket.listen(1)

print('等待客戶端連接...')
connection, client_address = server_socket.accept()

print('客戶端已連接:', client_address)

def request_verdict(req_bytes_frame):  # req_bytes_frame是字節(jié)數(shù)據(jù)b'x02x00x08x00x00x00x00x00x10x00x01x01x02x03x04x03'
    command = req_bytes_frame.hex()[22:26]  # 轉(zhuǎn)成16進(jìn)制字符串好數(shù)據(jù)處理
    if command in ["0104", "0401"]:  # 判斷讀寫
        return False # 讀
    elif command in ["0114", "1401"]:
        return True  # 寫
    else:
        raise ValueError("讀寫指令錯(cuò)誤!")

def write_response_frame(req_bytes_frame):
    response = "D00000FFFF030002000000"  # 寫成功則返回這一串?dāng)?shù)據(jù)
    content = req_bytes_frame.hex()[42:]  # 看一下客戶端想寫的內(nèi)容
    print("客戶端想要寫入的內(nèi)容:", bytes.fromhex(content).decode())
    return bytes().fromhex(response)

def read_response_frame(req_bytes_frame, res_data):
    header = "D00000FFFF03000C000000"  # 讀的響應(yīng)頭
    nums = req_bytes_frame.hex()[38:42]  # 獲取客戶端想要讀的寄存器個(gè)數(shù)
    act_nums_hex = nums[2:] + nums[:2]  # 涉及大端序和小端序,需要轉(zhuǎn)一下
    act_nums = int(act_nums_hex, 16)  # 得到實(shí)際數(shù)量
    res_data_hex = ''.join([hex(ord(c))[2:].zfill(2) for c in res_data])  # 將要返回的數(shù)據(jù)轉(zhuǎn)成16進(jìn)制字符串
    response = header + res_data_hex + '0'*(act_nums*2*2-len(res_data_hex))  # 根據(jù)請(qǐng)求數(shù)量返回對(duì)應(yīng)的內(nèi)容
    return bytes().fromhex(response)

try:
    while True:
        # 接收客戶端請(qǐng)求
        request = connection.recv(1024)
        print("001:", request)
        if request:
            flag = request_verdict(request)
            if flag:  # 響應(yīng)寫
                response = write_response_frame(request)
                print("002:",response)
            else:  # 響應(yīng)讀
                response = read_response_frame(request, "start")
                print("003:",response)
            connection.sendall(response)
finally:
    # 清理連接
    connection.close()

三、關(guān)于MC協(xié)議的整體實(shí)現(xiàn)

通過“二”,我們實(shí)現(xiàn)了一個(gè)基于MC協(xié)議的保持寄存器的讀寫服務(wù)器,但并沒有像pymodbus這種現(xiàn)成模塊那樣完整實(shí)現(xiàn),這里探討一下還可以做的事。

1、SLMP 3E幀實(shí)現(xiàn)步驟

實(shí)現(xiàn)SLMP(Seamless Message Protocol) 3E幀協(xié)議涉及到網(wǎng)絡(luò)通信、數(shù)據(jù)處理、錯(cuò)誤處理等多個(gè)步驟。以下是實(shí)現(xiàn)SLMP 3E幀的一般步驟:

(1)建立TCP連接:

在服務(wù)端,監(jiān)聽指定端口(通常是4999)。
在客戶端,連接到服務(wù)端的IP地址和端口。
(2)接收請(qǐng)求:

服務(wù)端接收客戶端發(fā)送的SLMP 3E幀請(qǐng)求。
解析SLMP 3E幀,獲取命令碼、子命令碼、數(shù)據(jù)等信息。
(3)處理請(qǐng)求:

根據(jù)SLMP 3E幀中的命令碼和數(shù)據(jù),執(zhí)行相應(yīng)的操作,如讀取、寫入、控制等。
處理請(qǐng)求可能涉及到對(duì)PLC或其他設(shè)備進(jìn)行讀寫操作,具體實(shí)現(xiàn)根據(jù)設(shè)備和應(yīng)用需求而定。
(4)生成響應(yīng):

根據(jù)請(qǐng)求處理的結(jié)果,生成SLMP 3E幀的響應(yīng)數(shù)據(jù)。
設(shè)置響應(yīng)幀的命令碼、子命令碼、數(shù)據(jù)等。
(5)發(fā)送響應(yīng):

將生成的SLMP 3E幀響應(yīng)數(shù)據(jù)發(fā)送回客戶端。
(6)錯(cuò)誤處理:

在處理請(qǐng)求和生成響應(yīng)的過程中,可能出現(xiàn)各種錯(cuò)誤,如無效命令、數(shù)據(jù)不合法等。
針對(duì)不同的錯(cuò)誤情況,生成相應(yīng)的錯(cuò)誤響應(yīng)幀。
(7)關(guān)閉連接:

當(dāng)通信結(jié)束或出現(xiàn)錯(cuò)誤時(shí),關(guān)閉TCP連接,釋放資源。
請(qǐng)注意,SLMP 3E幀協(xié)議具體的實(shí)現(xiàn)步驟和數(shù)據(jù)格式可能因具體設(shè)備和應(yīng)用而有所不同。在實(shí)際開發(fā)中,需要參考設(shè)備文檔和SLMP協(xié)議規(guī)范來進(jìn)行具體的實(shí)現(xiàn)。

2、SLMP協(xié)議規(guī)范

查閱三菱PLC關(guān)于SLMP的文檔!

SLMP的詳細(xì)規(guī)范通常由設(shè)備廠商提供,以便開發(fā)者能夠正確地使用該協(xié)議與設(shè)備進(jìn)行通信。規(guī)范文件通常包含SLMP協(xié)議的命令碼、數(shù)據(jù)格式、通信流程、錯(cuò)誤處理等方面的詳細(xì)信息。

3、為什么會(huì)有SLMP協(xié)議

SLMP(Seamless Message Protocol)協(xié)議是為了在自動(dòng)化領(lǐng)域(例如工業(yè)自動(dòng)化、制造業(yè)、機(jī)器人技術(shù)等)中實(shí)現(xiàn)設(shè)備之間的無縫通信而設(shè)計(jì)的。它提供了一種標(biāo)準(zhǔn)化的通信協(xié)議,使不同廠商、不同類型的設(shè)備能夠在同一個(gè)網(wǎng)絡(luò)上進(jìn)行通信,實(shí)現(xiàn)設(shè)備的互聯(lián)互通。

在現(xiàn)代工業(yè)自動(dòng)化系統(tǒng)中,通常涉及到各種各樣的設(shè)備,這些設(shè)備由不同的廠商制造,可能使用不同的通信協(xié)議和數(shù)據(jù)格式。為了實(shí)現(xiàn)這些設(shè)備之間的互聯(lián)互通,需要一種通用的、標(biāo)準(zhǔn)化的通信協(xié)議。SLMP就是為了滿足這種需求而被開發(fā)出來的。

SLMP協(xié)議的設(shè)計(jì)目標(biāo)包括:

標(biāo)準(zhǔn)化通信: 提供一種通用的通信協(xié)議,使得不同廠商生產(chǎn)的設(shè)備可以在同一個(gè)網(wǎng)絡(luò)上進(jìn)行通信。

靈活性: 允許不同類型的數(shù)據(jù)(例如狀態(tài)信息、控制命令等)通過同一個(gè)協(xié)議進(jìn)行傳輸。

高效性: 設(shè)計(jì)為高效的通信協(xié)議,以滿足工業(yè)自動(dòng)化系統(tǒng)對(duì)實(shí)時(shí)性和響應(yīng)速度的要求。

易用性: 設(shè)計(jì)為易于實(shí)現(xiàn)和配置,使得工程師能夠方便地將SLMP協(xié)議集成到他們的設(shè)備和系統(tǒng)中。

綜上所述,SLMP協(xié)議的存在使得不同類型的自動(dòng)化設(shè)備能夠方便地相互通信,實(shí)現(xiàn)了工業(yè)自動(dòng)化系統(tǒng)的互操作性和靈活性。

4、我是否可以自定義一套協(xié)議

你完全可以自定義一套通信協(xié)議,以滿足特定需求或者應(yīng)用場(chǎng)景。自定義通信協(xié)議通常涉及到以下幾個(gè)步驟:

確定通信需求: 首先,你需要明確通信雙方之間需要傳輸哪些數(shù)據(jù),以及數(shù)據(jù)的格式和類型。確定通信的數(shù)據(jù)結(jié)構(gòu)、命令類型、錯(cuò)誤處理機(jī)制等。

選擇傳輸方式: 確定通信采用的傳輸方式,可以是基于串口的通信(例如RS-232、RS-485)、基于網(wǎng)絡(luò)的通信(例如TCP/IP、UDP)、無線通信(例如Wi-Fi、藍(lán)牙)等。

制定協(xié)議規(guī)范: 定義協(xié)議的數(shù)據(jù)幀格式,包括幀頭、幀尾、校驗(yàn)碼等信息。確保通信雙方遵循相同的協(xié)議規(guī)范。

實(shí)現(xiàn)協(xié)議解析和封裝 在通信的發(fā)送端和接收端分別實(shí)現(xiàn)協(xié)議的封裝和解析邏輯。封裝就是將待發(fā)送的數(shù)據(jù)按照協(xié)議格式組織成數(shù)據(jù)幀,解析則是在接收端將接收到的數(shù)據(jù)幀按照協(xié)議格式解析成可處理的數(shù)據(jù)。

添加錯(cuò)誤處理和安全性: 考慮數(shù)據(jù)傳輸中可能出現(xiàn)的錯(cuò)誤情況,設(shè)計(jì)相應(yīng)的錯(cuò)誤處理機(jī)制,確保數(shù)據(jù)的完整性和可靠性。如果通信需要保密性,可以考慮加密通信數(shù)據(jù)。

測(cè)試和驗(yàn)證: 在實(shí)際環(huán)境中進(jìn)行測(cè)試和驗(yàn)證,確保自定義協(xié)議能夠正常工作,并且滿足通信需求。

請(qǐng)注意,自定義協(xié)議需要考慮通信的穩(wěn)定性、可靠性和安全性。在設(shè)計(jì)過程中,建議參考現(xiàn)有通信協(xié)議的設(shè)計(jì)經(jīng)驗(yàn),以及相關(guān)領(lǐng)域的最佳實(shí)踐。同時(shí),文檔化自定義協(xié)議的規(guī)范,以便未來的維護(hù)和擴(kuò)展。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜