1

私は、現場でシリアルデバイスからの測定値を記録する必要がある産業環境を扱っています。私の現在のセットアップには、Moxa 5150A または 5130 シリアル デバイス サーバに接続されたデバイスが含まれており、個々のデバイスの場所に応じて、有線または無線の手段を介してネットワークに接続されています。現在、データ収集を管理するために、ハードウェア ベンダーのソフトウェアに依存しています。現在のソフトウェアは Windows X86 ベースであり、以前のハードウェアの故障により、購入した新しいハードウェアでトラブルが後を絶ちません。Linux ドライバと互換性のために、Moxa シリアル サーバを選択しました。このデバイスは、RS-422 (4 線式半二重) 7 ビット 1 ストップ奇数パリティおよび NO フロー制御を介して通信し、要求されない限り情報を送信しません。

データベース (おそらく MySQL) に情報を保存する独自のソリューションの開発に取り組んでいます。端末通信に関しては、これは 2 つの部分に分かれています。リクエストを送信し、レスポンスを受信する必要があります。

現在までに、シリアル サーバー用の Moxa ドライバーを Linux サーバーにインストールしました。/dev/ttyrXX デバイスから読み取り、入力を解釈し、情報を mysql データベースにロードする bash スクリプトを作成しました。

      while read line
      do
      something something....
      done < /dev/ttyrXX

デバイスがオフラインになり、後でオンラインに戻ったときに適切に再起動するなど、スクリプトの小さなバグをまだ解決していませんが、スクリプトは私のニーズに合わせてデータを読み取り、ログに記録しています。

このソリューションは、2 つの要因に依存しています。

1) Moxa デバイスは FIFO をサポートし、複数の接続を同時に許可します。

2) 別の Windows マシンで実行されているベンダー提供のソフトウェアが、現在、情報の要求を送信しています。

Windows ベースのソフトウェアをまとめて削除する必要があります。/dev/ttyrXX に出力して目的のリクエストを行い、適切な応答を受け取り、最初のスクリプトで必要に応じてログに記録するスクリプトを作成してテストしました。

     some list of things
     for x in list
     do         
     printf "request" > /dev/ttyrXX
     done

ベンダー提供のソフトウェアで私が経験した主な問題の 1 つは、すべての要求に対してタイムリーな応答を受信することへのハードコーディングの依存性です。これにより、ウィンドウが完全にフリーズしたり、デバイスが不適切な時間にサービスを停止した場合にクラッシュしたりするなど、多くの問題が発生します。

連携して動作する 2 つのスクリプトは、非常に優れた間隔でデータを収集し、人間の介入が大幅に少なくなります。

これが私の質問です。Bash スクリプトと同等の結果を得るために Python で使用できる方法は何ですか?

ファイルを開いたり閉じたりする必要のない、printf または cat に相当する Python を見つけることができませんでした。さらに、私が調べたすべての端末インターフェイスには、組み込みまたは必須の応答待機またはあきらめる前の長い読み取りがあります。私はそこに何かが存在することを確信しています。私は Python の初心者であり、Python の能力を試してみるために数行しかコードを書いていないことを認めます。

はっきりさせてください。書いているときに、他のことを気にせずに自分の端末に書きたいです(気にしないスレッドまたは別のスクリプトを使用します)。次のテキストがいつ来るかを気にせずに端末から読みたいです。(終わりのないループを提案しているわけではありませんが、単に待機して入力を待つ必要があります)。昨日、今、または来週、他の人が何をしているのかを気にせずに、書き込みと読み取りを互いに完全に独立させたい/必要としています。

前もって感謝します。

必要に応じて、より詳細なコードを提供することもできますが、バグ修正よりも検索の方向性が必要であると感じています。私はまだアドバイスを完全に受け入れていますが、「これを決してしないでください....これのせいで...」タイプの入力

4

3 に答える 3

1

ファイルを読み取り/書き込み用に開き、各行を順番に読み取りたいようです。

with open(..., 'r+') as dev:
  for line in dev:
     ...
    print >>dev, 'foo'
于 2012-08-18T05:11:13.200 に答える
1

イグナシオが言っていることを拡張します。最も簡単な解決策は、起動時に開始される 2 つのスクリプトを用意することです。

それらの 1 つが開き、tty デバイスが開き、それを永遠にリッスンします。これはブロッキング読み取りです。EOF を受け取る (または到達する) まで、新しい入力行を探し続けます。おそらく、この場合、これは決して起こりません。次のようになります。

# tty reader

def listen_to_device():
    with open('/dev/ttyXX', 'r') as tty:
        for line in tty:
            create_db_record(line)

if __name__ == '__main__':
    listen_to_device()

これを完全に機能するコードにするために実装する必要があるのは、'create_db_record' 関数だけです。

2 番目のスクリプトは非常に似ている可能性があります。しかし、コマンドを含むディレクトリ内の特定のファイルを探し続ける可能性があります。いずれかが見つかると、それらを tty デバイスに 1 つずつ送信します。

# tty controller

import os
import shutil
import time

def wait_for_commands():
    while True:
        if os.path.exists('/tmp/commands.txt'):
            with open('/tmp/commands.txt', 'r') as c:
                for command in c:
                    send_command(command)
            shutil.move('/tmp/commands.txt', 'tmp/proccesed-' str(datetime.utcnow()))
        time.sleep(1)


def send_command(command):
    with open('/dev/ttyXX', 'w') as tty:
        # maybe do some additional changes to command here?
        tty.write(command)


if __name__ == '__main__':
    wait_for_command()

コマンドの処理コードを send_command 関数に追加して、commands.txt ファイル内の指示を非常に単純にすることができます。

于 2012-08-18T08:10:36.177 に答える
1

pyserial をお勧めします (ノンブロッキングで使用できます) が、RS232 以外のものを正しく処理するかどうかはわかりません。

ファイルを開いたり閉じたりする必要のない、printf または cat に相当する Python を見つけることができませんでした。

通常、ファイルを開いて .write() 関数 (printf と同等) または .readline() 関数を呼び出すだけです。これの何が問題なのですか?「cat」や「echo」、またはシェルスクリプトからのパイプを使用すると、これも裏でファイルを開いたり閉じたりします。なんらかの有線の理由 (カーネル ドライバーが問題を引き起こしているなど) でファイルを再度開く必要がある場合は、それを行う python 関数を記述できます。

さらに、私が調べたすべての端末インターフェイスには、組み込みまたは必須の応答待機またはあきらめる前の長い読み取りがあります。

シリアルライブラリは通常、書き込みではなく読み取りのみにタイムアウトがあります(ただし、書き込みの場合、カーネルドライバーには通常バッファがあり、書き込みが速すぎると理論的にオーバーフローする可能性があります...)。

私が見ていないのは、このタイムアウトがあなたにとってどのように問題であるかということです? 書き込みを行うプログラムと読み取りを行うプログラムの 2 つの個別の Python プログラムでターミナルを開くことができれば、問題は解決しますよね?

注意すべきことは、ファイルに対してブロッキングまたはノンブロッキング I/O を実行できることです。デフォルトでは、すべてがブロックされます。select()システム コール (これも Python から) を使用して、スレッドまたは個別のプロセスのあらゆるニーズを回避できます。Select は、ブロックせずにファイルを読み書きできる場合、例外が発生した場合 (デバイスが消えたなど)、またはタイムアウトが発生した場合 (設定した場合) に戻ります。

于 2012-08-18T08:34:33.953 に答える