Network-Interface

控制 rs-232 接收器,就好像它理解更新的 IP 協議一樣

  • October 18, 2016

我想在一個 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        

引用自:https://unix.stackexchange.com/questions/309317