
簡介圍繞阿特拉斯·科普柯 PowerFocus 6000 的 Open Protocol 開放協(xié)議附錄面向使用 PF6000 進(jìn)行遠(yuǎn)程控制、數(shù)據(jù)訂閱或二次開發(fā)的自動(dòng)化工程師、PLC 程序員與系統(tǒng)集成人員。文檔聚焦協(xié)議在 PF6000 上的實(shí)現(xiàn)差異幫助解決開發(fā)中對 MID 與修訂版本、Relay 及數(shù)字/模擬輸入信號、Pset 與 Job 選擇等細(xì)節(jié)把握不準(zhǔn)的問題。資源包僅含 1 個(gè) PDF 文件約 980KB為英文規(guī)范附錄便于離線查閱和現(xiàn)場對照內(nèi)容按章節(jié)梳理 MID 支持表、修訂版本支持、MID 64/65 舊結(jié)果數(shù)據(jù)處理以及緊固程序 Pset 選擇、批量大小和序列 Job 選擇等用法。已有 195 人學(xué)習(xí)下載。讀者可據(jù)此核對消息與版本支持邊界明確 Pset/Job 調(diào)用方式減少聯(lián)調(diào)階段的協(xié)議適配與排錯(cuò)成本適合需要落地 PF6000 通信接口、進(jìn)行上位機(jī)或 PLC 程序聯(lián)調(diào)的中高級開發(fā)者參考也可作為協(xié)議版本核對與接口調(diào)試的輔助清單。1. 產(chǎn)線上擰緊數(shù)據(jù)接不進(jìn) MES問題常出在開放協(xié)議附錄沒讀透產(chǎn)線上那臺擰緊控制器能不能把每次擰緊的扭矩、角度、判定結(jié)果直接吐給 MES很多時(shí)候卡住的不是網(wǎng)絡(luò)而是對開放協(xié)議附錄里那幾張 MID 表的理解。這份附錄針對某型號擰緊控制器下文簡稱 TC6的 Open Protocol 實(shí)現(xiàn)標(biāo)注 release 2.8 Rev.2、自 2.8.14 起生效核心內(nèi)容就三塊哪些 MID 能用、每個(gè) MID 支持到第幾修訂、繼電器和數(shù)字輸入的編號各代表什么。它解決的是“上位機(jī)按通用 Open Protocol 發(fā)報(bào)文控制器卻回錯(cuò)誤碼或不回”的問題適合做產(chǎn)線數(shù)據(jù)采集、PLC 遠(yuǎn)程控制、MES 集成的工程師也適合剛接手?jǐn)Q緊工位、需要快速判斷“這個(gè)功能到底能不能遠(yuǎn)程做”的人。附錄不是入門教程它默認(rèn)你已經(jīng)知道報(bào)文長什么樣所以下面從幀結(jié)構(gòu)開始補(bǔ)課再把表里的坑逐條拆開。2. 幀結(jié)構(gòu)與握手先把 0001/0002 跑通再談?dòng)嗛?.1 四段式幀長度頭、MID、數(shù)據(jù)體、空終止Open Protocol 走 TCP報(bào)文不是 JSON也不是定長結(jié)構(gòu)體而是“長度 消息號 定長字段拼接 空字符”的四段式。長度頭是 4 字節(jié) ASCII 十進(jìn)制值等于 MID 加數(shù)據(jù)體的字節(jié)數(shù)不含長度頭自身也不含結(jié)尾的 NUL。MID 是 4 字節(jié) ASCII比如0001、0061。數(shù)據(jù)體里的字段按附錄規(guī)定的固定長度順序排列數(shù)字通常右對齊補(bǔ)空格或補(bǔ)零具體補(bǔ)法以你手上的字段表為準(zhǔn)。段長度示例說明Length4 字節(jié) ASCII0020MID Data 的字節(jié)數(shù)MID4 字節(jié) ASCII0001消息標(biāo)識Data變長0060000101定長字段順序拼接NUL1 字節(jié)\x00報(bào)文終止先把編解碼寫對再談業(yè)務(wù)。下面這段代碼只做兩件事把 MID 和數(shù)據(jù)拼成可發(fā)送的字節(jié)流從 socket 里按長度頭精確讀一幀。很多聯(lián)調(diào)翻車就翻在“一次 recv 把兩幀粘在一起”或者“長度頭把 NUL 也算進(jìn)去”。import socket def encode_frame(mid: str, data: str ) - bytes: # 長度 MID(4) Data不含長度頭自身和結(jié)尾 NUL payload f{mid}{data} length f{len(payload):04d} return (length payload).encode(ascii) b\x00 def recv_exact(sock: socket.socket, n: int) - bytes: buf b while len(buf) n: chunk sock.recv(n - len(buf)) if not chunk: raise ConnectionError(peer closed) buf chunk return buf def recv_frame(sock: socket.socket) - tuple[str, str]: # 先讀 4 字節(jié)長度頭再按長度讀 MID Data最后吞掉 1 字節(jié) NUL len_raw recv_exact(sock, 4) total int(len_raw.decode(ascii)) body recv_exact(sock, total).decode(ascii) recv_exact(sock, 1) # NUL return body[:4], body[4:]encode_frame里最容易錯(cuò)的是長度計(jì)算把 NUL 算進(jìn)去控制器會多讀一個(gè)字節(jié)后續(xù)所有幀錯(cuò)位少算 MID控制器會把數(shù)據(jù)體開頭當(dāng)成下一個(gè)長度頭。recv_frame必須用循環(huán)讀滿不能假設(shè)一次recv就能拿到完整幀工業(yè)現(xiàn)場交換機(jī)延遲一高半幀到達(dá)是常態(tài)。2.2 最小客戶端連接、發(fā) 0001、收 0002握手只涉及三個(gè) MID0001 通信啟動(dòng)、0002 啟動(dòng)確認(rèn)、0003 通信停止。0001 的數(shù)據(jù)體按附錄是定長字段常見做法是帶 revision、cell ID、channel ID 三個(gè)字段不同版本的字段表可能還要求控制器序列號發(fā)之前對照你手上的附錄確認(rèn)一遍別直接抄別人的報(bào)文。revision 填 6因?yàn)楦戒洷?1 里 0001 的 Revision 列寫的是 6表示 0 到 6 都支持填高版本控制器會按自己的上限回退。HOST, PORT 192.168.1.50, 4545 # 控制器實(shí)際 IP 和端口以現(xiàn)場為準(zhǔn) sock socket.create_connection((HOST, PORT), timeout5) sock.settimeout(5) # revision 3 位、cell ID 4 位、channel ID 2 位按附錄字段表拼接 start_data 006 0001 01 sock.sendall(encode_frame(0001, start_data)) mid, data recv_frame(sock) print(mid, repr(data)) # 期望 0002data 里帶控制器協(xié)商后的 revision這段代碼跑通的標(biāo)準(zhǔn)不是“沒報(bào)錯(cuò)”而是收到 0002 且里面的 revision 不低于你后續(xù)要用的 MID 所需版本。如果收到 0004先別懷疑網(wǎng)絡(luò)按錯(cuò)誤碼查附錄常見是 cell ID 或 channel ID 長度不對或者控制器已經(jīng)有一條 Open Protocol 連接占著。0002 里的 revision 是控制器實(shí)際接受的版本后續(xù)能力判斷以它為準(zhǔn)不要拿你發(fā)送的 6 硬編碼。2.3 修訂號協(xié)商與 0004/0005 的判讀0004 是命令錯(cuò)誤0005 是命令接受這兩個(gè)是同步回復(fù)和訂閱推送共用同一條 TCP 連接。也就是說你發(fā)一條 0018 選 Pset可能先收到 0005再收到 0015 的 Pset 已選訂閱推送中間還夾著別的工位觸發(fā)上來的 0061 結(jié)果??蛻舳瞬荒芗僭O(shè)“發(fā)一條收一條”必須按 MID 做分發(fā)把 0004/0005 當(dāng)命令回執(zhí)把 0015/0035/0061 當(dāng)異步事件。修訂號在附錄表里是累計(jì)上限不是“只支持這一個(gè)版本”。比如 0061 寫 8意思是 0 到 8 的修訂都支持你按修訂 8 的字段表解析控制器不會因?yàn)槟闶切驴蛻舳司徒导?。反過來如果某個(gè) MID 寫的是-比如 0044 斷開工具請求、0130 Job off那就是真不支持發(fā)過去只會拿 0004別在代碼里留分支幻想它某天會通。3. MID 能力表怎么讀修訂上限、p 標(biāo)記與客戶端裁剪3.1 修訂號是累計(jì)上限不是逐個(gè)枚舉附錄表 1 有三列關(guān)鍵信息MID、Name、Revision。Revision 數(shù)字表示“從 0 到這個(gè)數(shù)字全都支持”所以看到 0001 是 6、0002 是 6、0061 是 8不要理解成“只支持第 6 版”。真正要小心的是帶p的行比如 0002 是6 p、0012 是4 p、0015 是1 P、0033 是2 p、0041 是5 p、0061 是8 p、0065 是8p。p的意思是“至少有一個(gè)修訂是部分支持”不是全支持也不是不支持。讀這張表的正確姿勢是先按 MID 找行再看 Revision 判斷“能不能用”最后看有沒有p判斷“要不要探測”。比如 0012 參數(shù)集數(shù)據(jù)上傳請求是4 p你按修訂 4 發(fā)過去控制器可能只回部分字段0065 老結(jié)果上傳回復(fù)是8p附錄專門提示“部分參數(shù)不支持”解析時(shí)不能按完整字段表硬解否則字段錯(cuò)位扭矩值會變成角度值。3.2 p 標(biāo)記半支持功能的探測式啟用p標(biāo)記的功能不能靠文檔拍板得靠探測。常見做法是客戶端啟動(dòng)后先跑一遍能力探測把要用的 MID 各發(fā)一條最小請求記錄返回的 MID 和錯(cuò)誤碼。比如 0250 選擇器插座信息訂閱是1 P你先訂閱看 0251 是否回、0252 是否確認(rèn)如果 0251 回了但字段明顯缺就降級到只讀部分字段不要阻塞主流程。探測要有超時(shí)和次數(shù)上限別在啟動(dòng)階段死等。下面這段能力表把“支持 / 部分支持 / 不支持”分開存后面所有業(yè)務(wù)分支都查這張表避免代碼里到處寫if mid 0061。CAPS { 0001: {rev: 6, partial: False}, 0012: {rev: 4, partial: True}, 0018: {rev: 1, partial: False}, 0038: {rev: 2, partial: False}, 0061: {rev: 8, partial: True}, 0065: {rev: 8, partial: True}, 0215: {rev: 2, partial: False}, } def can_use(mid: str, need_rev: int) - str: cap CAPS.get(mid) if not cap: return unknown # 附錄沒列按不支持處理 if cap[rev] need_rev: return unsupported # 修訂不夠 return probe if cap[partial] else fullneed_rev是你業(yè)務(wù)實(shí)際要用的字段所在修訂不是控制器上限。partial為 True 時(shí)返回probe調(diào)用方必須走探測分支返回full才能直接按完整字段表解析。這張表建議從附錄手工抄一遍別用腳本爬字段名和p標(biāo)記抄錯(cuò)一個(gè)后面排查成本遠(yuǎn)高于抄表的時(shí)間。3.3 用能力矩陣裁剪客戶端功能能力矩陣的用處不是“記錄文檔”而是“決定客戶端啟動(dòng)后開哪些線程”。比如 0060 結(jié)果訂閱是 8、非 partial可以放心開主訂閱0064 老結(jié)果上傳請求是 8、非 partial但 0065 回復(fù)是8p那補(bǔ)拉線程就要允許字段缺失0215 IO 設(shè)備狀態(tài)回復(fù)是 2、非 partialIO 巡檢線程可以全量解析。裁剪時(shí)按“業(yè)務(wù)最小集”來MES 只要扭矩、角度、判定那就只依賴 0061 的對應(yīng)字段不要因?yàn)?0061 支持到修訂 8 就把所有字段都解析一遍。字段越多版本差異帶來的錯(cuò)位風(fēng)險(xiǎn)越大。我的習(xí)慣是給每個(gè) MID 寫一個(gè)字段定義表解析函數(shù)按表走表里標(biāo)清楚“修訂幾開始有”“是否可能缺失”這樣換現(xiàn)場、換控制器版本時(shí)只改表不改代碼。4. 結(jié)果數(shù)據(jù)鏈路0060/0061/0062 與 0064/0065 的補(bǔ)拉策略4.1 訂閱、推送、確認(rèn)的三段式結(jié)果數(shù)據(jù)的主鏈路是 0060 訂閱、0061 推送、0062 確認(rèn)。0060 發(fā)出去后控制器不會回一個(gè)“訂閱成功”的獨(dú)立 MID而是每次有擰緊結(jié)果就推一條 0061客戶端收到 0061 后必須回 0062 確認(rèn)否則控制器可能認(rèn)為客戶端處理不過來后續(xù)推送行為會變。0063 是取消訂閱工位切換或客戶端退出時(shí)發(fā)別直接斷 TCP斷線重連后訂閱狀態(tài)不一定保留。這里有個(gè)時(shí)序細(xì)節(jié)0062 的確認(rèn)數(shù)據(jù)里要帶 0061 里的結(jié)果序號或時(shí)間標(biāo)識具體字段按附錄表來。確認(rèn)發(fā)早了、發(fā)晚了、帶錯(cuò)序號表現(xiàn)都是“前幾條能收后面不推了”。我一般把 0061 的解析和 0062 的組裝放在同一個(gè)函數(shù)里解析完立刻組確認(rèn)中間不做落庫、不做 HTTP 上報(bào)避免網(wǎng)絡(luò)抖動(dòng)把確認(rèn)拖過控制器的等待窗口。4.2 0061 報(bào)文字段與解析0061 是定長字段拼接字段多而且修訂 8 比早期版本多出不少字段。解析不要手寫切片下標(biāo)用字段定義表驅(qū)動(dòng)每個(gè)字段給名字、長度、起始偏移或按順序累加解析函數(shù)按表走。這樣控制器修訂變了只改表。# 字段表按你手上的附錄修訂 8 抄長度單位是字符 RESULT_FIELDS [ (cell_id, 4), (channel_id, 2), (torque_status, 2), (angle_status, 2), (torque, 6), (angle, 5), # 其余字段按附錄順序繼續(xù)補(bǔ) ] def parse_result(data: str) - dict: out, pos {}, 0 for name, length in RESULT_FIELDS: out[name] data[pos:pos length].strip() pos length if pos ! len(data): out[_unparsed] data[pos:] # 長度對不上時(shí)留證據(jù)別靜默丟 return outtorque和angle拿到的是字符串轉(zhuǎn) float 前先判空_unparsed是排錯(cuò)用的長度對不上說明字段表版本和控制器不一致這時(shí)候不要強(qiáng)行解析把原始報(bào)文落盤比對附錄字段表。狀態(tài)字段是數(shù)字碼別直接展示給業(yè)務(wù)按附錄的判定碼表翻譯成 OK/NOK。4.3 0064/0065 老結(jié)果數(shù)據(jù)的特殊處理0064 是按序號補(bǔ)拉歷史結(jié)果0065 是回復(fù)。附錄把這一對單獨(dú)拎出來講原因是 0065 的字段支持和 0061 不完全一樣而且 0065 帶p標(biāo)記部分參數(shù)可能拿不到。補(bǔ)拉的正確用法是“斷點(diǎn)續(xù)傳”客戶端本地記一個(gè)已處理的最大結(jié)果序號重連后從該序號之后開始發(fā) 0064收到 0065 解析、落庫、更新游標(biāo)。補(bǔ)拉要防重0064 的序號邊界是開區(qū)間還是閉區(qū)間按附錄來如果不確定寧可多拉一條落庫時(shí)按“控制器序列號 結(jié)果序號”做唯一鍵去重。0065 的字段缺失不要當(dāng)錯(cuò)誤缺失字段填 None不要用 0 代替否則報(bào)表里會出現(xiàn)一批扭矩為 0 的假數(shù)據(jù)。補(bǔ)拉線程和 0061 訂閱線程要互斥寫游標(biāo)常見做法是加一把本地鎖或者讓補(bǔ)拉只在上電初始化階段跑跑完再開訂閱。5. 控制面Pset/Job 選擇、批量計(jì)數(shù)與繼電器/數(shù)字輸入5.1 Pset 選擇的三種路徑Pset 選擇在附錄里對應(yīng) 0010 到 0020 一組 MID。最直接的是 0018 選擇參數(shù)集數(shù)據(jù)體帶 Pset 編號0014 訂閱“當(dāng)前選中的 Pset”控制器會在切換時(shí)推 00150016 是 0015 的確認(rèn)。0010/0011 是上傳 Pset ID 列表0012/0013 是上傳 Pset 數(shù)據(jù)這兩條都帶p字段可能不全適合做展示不適合做控制依據(jù)。選 Pset 要注意冪等同一條 0018 連發(fā)兩次控制器可能回兩個(gè) 0005也可能第二次回 0004取決于當(dāng)前狀態(tài)??蛻舳瞬灰?yàn)闆]收到 0015 就瘋狂重發(fā)正確做法是發(fā) 0018 后等 0005 或 0004再用 0014 訂閱確認(rèn)最終選中的是哪個(gè)。如果業(yè)務(wù)要求“選錯(cuò)就停線”把 0015 里的 Pset 編號和期望值比對不一致走報(bào)警不要只信 0005。5.2 批量大小與 Lock at batch done0019 設(shè)置 Pset 批量大小0020 重置批量計(jì)數(shù)0021 到 0024 是 Lock at batch done 的訂閱、上傳、確認(rèn)、取消訂閱。附錄對 0022 有一句關(guān)鍵提示在 TC6 上這個(gè)信號表示“被批量序列完成鎖定”。也就是說批量做到數(shù)后工具會被鎖不是簡單的計(jì)數(shù)器歸零。現(xiàn)場常見需求是“一托盤 N 顆做完鎖槍換托盤再解鎖”。做法是0019 設(shè) N訂閱 0021收到 0022 后置鎖定標(biāo)志換托盤時(shí)發(fā) 0020 重置計(jì)數(shù)再發(fā) 0018 重選 Pset 或 0038 重選 Job。注意 0020 只重置計(jì)數(shù)不解除鎖定解除鎖定要靠重新選 Pset/Job 或附錄里對應(yīng)的解鎖動(dòng)作。順序反了表現(xiàn)是“計(jì)數(shù)歸零了但槍還是按不動(dòng)”。5.3 Job 選擇與重啟Job 相關(guān)是 0030 到 0039。0038 選擇 Job數(shù)據(jù)體帶 Job 編號0039 是 Job 重啟把當(dāng)前 Job 的批量計(jì)數(shù)和步驟回到起點(diǎn)。0034 訂閱 Job 信息0035 推送0036 確認(rèn)。和 Pset 一樣0038 之后不要只等 0005要等 0035 確認(rèn)當(dāng)前 Job 編號。Job 和 Pset 的關(guān)系容易搞混Pset 是擰緊參數(shù)集Job 是包含多個(gè) Pset 和步驟的序列。產(chǎn)線上如果按車型切換通常選 Job如果只是換一種螺栓參數(shù)選 Pset 就夠。兩者都選的時(shí)候以最后一條生效的命令為準(zhǔn)所以客戶端要有明確的“當(dāng)前上下文”狀態(tài)機(jī)別讓 MES 的 Pset 切換和 PLC 的 Job 切換打架。5.4 繼電器編號空間0215 回復(fù)里的分段規(guī)律0215 是 IO 設(shè)備狀態(tài)回復(fù)附錄表 22 列了繼電器編號到功能的映射。編號不是連續(xù)的語義塊但有幾段規(guī)律可循00 到 30 是常用狀態(tài)01 OK、02 NOK、05 低扭矩、06 高扭矩、12 Job OK、13 Job NOK、18 控制器就緒、19 工具就緒31 到 46 是 Pset/Job 運(yùn)行位47 到 142 是擴(kuò)展?fàn)顟B(tài)、同步狀態(tài)、外部控制位251 到 266 是已完成批量和剩余批量的位域。解析 0215 時(shí)不要按“編號 數(shù)組下標(biāo)”硬編碼用字典映射表里沒有的編號留unknown。位域那幾段Running Pset bit0-8、Running Job bit0-8、Completed Batch bit0-7、Remaining Batch bit0-7要按位拼不能當(dāng)獨(dú)立布爾量讀否則批量 3 會被讀成“bit0 和 bit1 都亮”。5.5 數(shù)字輸入0220 到 0225 的訂閱與設(shè)置數(shù)字輸入相關(guān)是 0220 訂閱、0221 推送、0222 確認(rèn)、0223 取消訂閱、0224 設(shè)置功能、0225 重置功能。附錄表里 DigIn 編號 00 是 Off01 Reset batch02 Unlock tool05 禁止擰緊06 禁止松開07 遠(yuǎn)程啟動(dòng)脈沖08 遠(yuǎn)程啟動(dòng)持續(xù)10 批量遞增12 中止 Job16 到 19 是 Pset 選擇位。0224 下發(fā)前先確認(rèn)該 DigIn 沒有被本地配置占用下發(fā)后用 0220 訂閱回讀比對功能號是否生效?;刈x不一致常見原因是控制器處于手動(dòng)模式或該輸入被更高優(yōu)先級的邏輯接管不是報(bào)文寫錯(cuò)了。6. 避坑與排查六個(gè)把聯(lián)調(diào)拖到后半夜的現(xiàn)場問題6.1 連接層長度頭算錯(cuò)導(dǎo)致粘包和錯(cuò)位現(xiàn)象是前幾條報(bào)文正常跑幾分鐘后解析全亂扭矩字段里出現(xiàn)字母。原因多半是長度頭把 NUL 算進(jìn)去了或者數(shù)據(jù)體里有中文字符導(dǎo)致字節(jié)數(shù)和字符數(shù)不一致。解決編碼統(tǒng)一用 ASCII長度按字節(jié)算不用len(str)混算接收端嚴(yán)格按“讀長度、讀 body、讀 NUL”三步走任何一步超時(shí)就整幀丟棄并重連不要試圖從半幀里恢復(fù)。6.2 時(shí)序?qū)佑嗛喭扑秃兔罨貜?fù)混在一條流里現(xiàn)象是發(fā) 0018 后收到的第一條是 0061代碼把它當(dāng) 0018 的回復(fù)解析報(bào)字段錯(cuò)。原因是客戶端假設(shè)“請求-響應(yīng)”一問一答。解決按 MID 分發(fā)0004/0005 進(jìn)命令回執(zhí)隊(duì)列0015/0035/0061/0071 進(jìn)事件隊(duì)列命令回執(zhí)用“MID 序號”匹配匹配不上就超時(shí)不要拿事件報(bào)文頂包。6.3 數(shù)據(jù)層0061 字段表版本和控制器不一致現(xiàn)象是扭矩值看起來像角度值或者判定狀態(tài)永遠(yuǎn)是同一個(gè)碼。原因是字段表抄的是舊修訂控制器按新修訂推了更多字段偏移整體后移。解決先讀 0002 里的 revision再查附錄確認(rèn) 0061 對應(yīng)修訂的字段表解析函數(shù)保留_unparsed長度對不上就落原始報(bào)文別靜默截?cái)唷?.4 控制層Pset 批量計(jì)數(shù)沒重置第二托盤直接鎖槍現(xiàn)象是第一托盤正常換托盤后第一顆就報(bào)批量完成。原因是 0019 的計(jì)數(shù)沒隨托盤重置0022 的鎖定標(biāo)志也沒清。解決把“換托盤”做成一個(gè)固定序列——0020 重置計(jì)數(shù)、0018 重選 Pset、等 0015 確認(rèn)、再放行啟動(dòng)序列里任何一步超時(shí)都停線不要跳過繼續(xù)跑。6.5 補(bǔ)拉層0064/0065 重復(fù)入庫現(xiàn)象是斷線重連后報(bào)表里同一顆螺栓出現(xiàn)兩條記錄。原因是補(bǔ)拉起點(diǎn)用了“最后一條的序號”而不是“最后一條序號 1”或者 0064 的序號邊界理解反了。解決本地游標(biāo)只存“已確認(rèn)處理完的最大序號”補(bǔ)拉從游標(biāo)之后開始入庫用“控制器標(biāo)識 結(jié)果序號”做唯一鍵重復(fù)數(shù)據(jù)在數(shù)據(jù)庫層攔掉。6.6 部署層重連后訂閱丟了數(shù)據(jù)不再推送現(xiàn)象是網(wǎng)絡(luò)閃斷恢復(fù)后TCP 通了但 0061 一條不來。原因是訂閱狀態(tài)掛在舊連接上重連后沒有重發(fā) 0060/0014/0034。解決把“連接建立”和“業(yè)務(wù)就緒”分成兩個(gè)狀態(tài)重連成功后按能力表重放訂閱命令每條訂閱都等對應(yīng)的確認(rèn)或首條推送全部就緒才把工位狀態(tài)置為可生產(chǎn)。7. 進(jìn)階用 0064 做斷點(diǎn)續(xù)傳再用回放驗(yàn)證整條鏈路7.1 把補(bǔ)拉做成可重入的游標(biāo)機(jī)0064/0065 最適合做斷點(diǎn)續(xù)傳但前提是游標(biāo)可重入。我的做法是給每個(gè)控制器維護(hù)一個(gè)last_seq補(bǔ)拉線程只做三件事讀last_seq、發(fā) 0064、收到 0065 后解析并更新last_seq。更新放在落庫成功之后落庫失敗就不推進(jìn)游標(biāo)下次重跑自然重拉。這樣即使補(bǔ)拉中途進(jìn)程崩了重啟后也不會漏數(shù)最多重復(fù)一條靠唯一鍵攔住。def backfill(sock, last_seq: int, batch: int 50): seq last_seq 1 while True: # 0064 數(shù)據(jù)體按附錄拼起始序號 數(shù)量 sock.sendall(encode_frame(0064, f{seq:010d}{batch:04d})) mid, data recv_frame(sock) if mid 0004: break # 沒有更多歷史結(jié)果 if mid ! 0065: continue # 跳過異步事件別在這里解析 row parse_old_result(data) save_once(row) # 唯一鍵去重 seq row[seq] 1 # 落庫成功才推進(jìn)last_seq建議持久化到本地 SQLite 或 Redis不要只放內(nèi)存。batch不要一次拉太大現(xiàn)場控制器歷史緩沖有限拉太多會超時(shí)拉到 0004 就停不要靠“連續(xù)空回復(fù)”判斷結(jié)束。7.2 上線前的回放驗(yàn)證聯(lián)調(diào)最后一步不是“能收數(shù)”而是“回放能對上”。我會把現(xiàn)場抓的原始報(bào)文存成二進(jìn)制文件用同一套解析代碼離線跑一遍和控制器面板上顯示的結(jié)果逐條比對。驗(yàn)收項(xiàng)至少覆蓋0001/0002 握手 revision 一致、0061 扭矩和角度與面板一致、0064 補(bǔ)拉條數(shù)與面板歷史條數(shù)一致、0018 選 Pset 后 0015 回讀一致、0020 重置后 0022 鎖定標(biāo)志能清掉。驗(yàn)收項(xiàng)通過標(biāo)準(zhǔn)失敗先看握手0002 revision ≥ 業(yè)務(wù)所需0004 錯(cuò)誤碼、連接占用結(jié)果訂閱0061 連續(xù)推送且 0062 確認(rèn)無積壓確認(rèn)序號、字段表版本歷史補(bǔ)拉0065 條數(shù)與面板一致、無重復(fù)游標(biāo)邊界、唯一鍵Pset 選擇0015 回讀編號與下發(fā)一致0005/0004、當(dāng)前模式批量鎖定0022 置位后 0020 能重置重置順序、Job 狀態(tài)回放通過再上產(chǎn)線別在工位上拿真螺栓試錯(cuò)。從那以后我每次接新的擰緊控制器都先把附錄表 1 抄成能力表、把 0061 字段表抄成解析表、再抓一段原始報(bào)文離線回放三件事做完才連現(xiàn)場網(wǎng)絡(luò)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取