控制 rs-232 接收器,就好像它理解更新的 IP 協議一樣
我想在一個 linux 機器上設置一個服務,作為我的舊 RS-232 控制的 Onkyo 接收器和我的本地網路之間的橋樑。到目前為止,我可以使用 socat 談論一種方式:
sudo socat tcp-l:60128,reuseaddr,fork file:/dev/ttyUSB0,nonblock,raw,echo=0,crnl,waitlock=/ttyUSB0.lock &
這讓我可以更改音量、源等設置,但返回確認更改的回复缺少一個簡單的字元串,較新的配備乙太網的接收器在其回復中包含該字元串。結果,我不能使用它來控制使用目前電話應用程序的接收器,這些應用程序期望乙太網啟用單元提供的響應。
有沒有辦法讓 socat 將附加字元串作為響應的一部分包含在內,或者我可以在一些程式碼的任一側獲取兩個 socat 實例,這些實例決定何時何地向消息中添加額外的字元串?
舊 RS-232 和新 IP 方法的 Onkyo 協議在此 Excel 表中描述,如果有幫助:http: //blog.siewert.net/files/ISCP%20AV%20Receiver%20v124-1.xls
所有各種現代 onkyo 控制應用程序發送的自動檢測請求“!xECNQSTN”預計會得到如下回复:“!1ECNTX-NR609/60128/DX”並且該請求發生在每次狀態更改(如音量增大、音量減小)之後等,所以看起來我需要做一些事情,比如讓兩個 socat 實例執行,中間有一些邏輯。
我總是可以得到一個新的現代接收器,但這會更令人滿意:o)
任何想法如何做到這一點都非常受歡迎!
你可能需要更複雜的東西,比如在 Python 中,因為乙太網協議中似乎有一些二進製文件,但首先你可以使用 bash 腳本,比如
~/myonkyo
:#!/bin/bash exec 2>/dev/tty set -x tty=/dev/ttyUSB0 stty -F $tty raw clocal -echo exec 3<>$tty echo "connection" >&2 while IFS= read -r -d $'\x1a' cmd do echo "$cmd" >&3 echo "!1ECNTX-NR609/60128/DX" done
通過以下方式在每個連接上從 socat 啟動腳本:
$ socat tcp -l: 60128, 重用地址系統: ~/myonkyo
您應該嘗試不為此而生。如果您需要 for
ttyUSB0
,則暫時將其 chown 或將自己放入正確的組(撥出?)以進行訪問。該腳本在每個連接上執行,並且對於調試使用
/dev/tty
您執行它的位置作為標準錯誤。它以 fd 3 的形式打開串列埠。它將以“EOF”字元 0x1a 結尾的輸入行讀取到cmd
中,然後將其寫入串列埠,然後寫入標準輸出,即乙太網,即您提供的範例字元串。您將不得不辨識您收到的輸入命令,將其轉換為等效的 rs232 協議並回复。
這樣的事情最大的問題是,如果協議是非同步的(有時任何一端都可以發送),您將不得不做些什麼
socat
並建構一個事件循環,select(2)
以便能夠讀取碰巧發送的人。這需要一些實際的程式語言(Python、Perl?)並且可能需要一些時間來適應。但是,如果協議是同步的(在任何時候只有一方可以通話),那麼您可以使用一次從一端讀取的程序。該程序將需要解釋協議以了解在任何給定點應該由哪一方通話,否則它可能會卡住等待來自錯誤端的輸入,而無需通過任何進一步的寫入。
要從網路與您的程序對話,您可以使用
socat tcp-l:60128,reuseaddr exec:/path/to/my_filter_prog
(或在程序本身中實現網路套接字)執行它。對於另一端,要麼socat
從程序呼叫另一個與串列埠對話,要麼打開串列埠直接從程序中。一個模擬 Bash 腳本可能看起來像這樣,
coproc
用於打開兩個管道到另一個管道以socat
與串列埠通信。(請注意,我並沒有真正查看實際的協議描述。)coproc socat - file:/dev/ttyUSB0,nonblock,raw,echo=0,crnl,waitlock=/ttyUSB0.lock serin=${COPROC[0]} serout=${COPROC[1]} # assume we have stdin/stdout connected to the other end, # as with socat tcp-listen:... exec:./this while true ; do # read a command from stdin, pass it through to serial read -r cmd echo "$cmd" >&$serout # do we need to read and pass another line at this point? # might depend on the command, but we need to know that. # read the reply and pass it through read -r reply <&$serin # add/modify something based on the command or the reply? echo "$reply" if [ "$cmd" = "!xECNQSTN" ] ; then echo "!1ECNTX-NR609/60128/DX" fi done