1

私は tcl の初心者ですが、tcl を使用する非常に複雑なシステム (ハードウェアとソフトウェア) を受け取ったので、1 つのことをしなければなりません。このハードウェアには、tcl スクリプトで読み取ることができるインターフェイスがあります。たとえば、電圧レベルを読み取るコマンドを送信すると、そのハードウェアはポーリングされた値で応答する必要があります (私の知る限り、エンジニアリング値、生の値などを含む tcl リストとして提供されます)。

私がする必要があるのは、プールされた値を使用してリアルタイム (1 秒ごとに新しい値) グラフを作成することであり、いくつかのデータ分析ソフトウェア (DAS) のグラフ作成機能を使用する必要があります。このソフトウェアが多くのデータ IO アクセス方法を使用できると仮定すると、tcl からデータ値を渡す最良の方法は何ですか? たとえば、ファイルに書き込んでからDASでファイルを読み取ることができますが、この場合、開いているファイルへのアクセスまたは同期に問題があると思います。

その DAS から tcl スクリプトを実行できれば、もっと簡単な作業になると思いますが、今はそれが不可能なようです。そのシステム固有のソフトウェアからスクリプトを開始する必要があるようです。

ヘルプ、ヒントなどは大歓迎です。

宜しくお願いします

4

3 に答える 3

3

@Vishwadeep: あなたはこれについて間違った方法で考えています。1 ピリオド待ってから何かを実行する代わりに、Tk は、ある程度の遅延後に実行するタスクのスケジューリングをサポートしています。これはまったく同じafterコマンドを使用しますが、遅延が期限切れになったときに実行されるプロシージャまたはスクリプトを指定します。2 つのモデルの違いは、このような多数のリーダーを一緒にチェーン化することを考えると、重要になります。したがって、代わりに次のようなものを使用する必要があります。

proc schedule_xx_update {interval} {
    variable id_xx
    set values [get_value_from_source]
    display_value $values
    set xx_id [after $interval schedule_xx_update]
}

proc stop_xx_updates {} {
    variable id_xx
    after cancel $id_xx
}

connect_to_device
schedule_xx_update 1000
vwait ::forever

vwait最後に、Tcl イベント ループの実行が開始されます。それを入力する前に、指定された遅延後に実行される読み取りおよび表示関数をスケジュールし、完了したら再び実行するように再スケジュールします。追加のリーダーを追加することはかなり明白です。

元の質問: デバイスの出力を読み取るために API 呼び出しまたはコマンドを使用している場合は、上記を使用できるはずです。デバイスがチャネル (ファイルまたはシリアル チャネル) を使用して応答する可能性があります。その場合fileeventは、チャネルでデータが利用可能になったときにプロシージャを呼び出すイベントを発生させる代わりに使用して調査する必要があります。

于 2013-09-13T11:52:33.493 に答える
2

ここでソケットベースのアプローチ:

# Use port 12345
socket -server accept_client 12345
proc accept_client {sock from port} {
    fconfigure $sock -blocking 0 -buffering line
    fileevent $sock readable [list readsock $sock]
    lappend ::clients $sock
}
proc readsock {sock} {
    catch {read $sock}
    if {[eof $sock]} {
       global clients
       set pos [lsearch -exact -- $clients $sock]
       if {$pos != -1} {
           set clients [lreplace $clients $pos $pos]
       }
       close $sock
    }
}

proc broadcastValues {} {
     global clients
     after 1000 broadcastValues
     if {![llength $clients]} {
         # No client connected
         return
     }
     # You have to modify the next line
     set data [lindex [GetTheDataHere] 1]
     foreach client $clients {
         # The data is seperated by a newline (\r\n)
         puts $client $data
     }
}

after idle broadcastValues
vwait forever; # Enter the event loop.

ローカルマシンでのみリッスンする場合はソケットに渡すなどの追加のチェックを行う-myaddr 127.0.0.1か、このIPがaccept_clientで接続できるかどうかを確認できます(接続しclose $sockない場合のみ)。

必要なデータのインデックスを自分で見つける必要があります。私が使用1したのは、リストの 2 番目の要素です。GetDataHereそして、値を返すコマンドに置き換える必要があります。

プロトコルは単純です: 1 行ごとに 1 つの値、1 秒ごとに新しい値。

于 2013-09-13T12:31:26.507 に答える