1

我完全是 tcl 的菜鸟,但我收到了使用 tcl 的相当复杂的系统(硬件和软件),我必须做一件事。该硬件具有我可以在 tcl 脚本中读取的接口。例如,我可以发送命令来读取一些电压电平,并且硬件应该以轮询值响应(AFAIK 它以 tcl 列表的形式出现,带有工程值、原始值等)。

我需要做的是使用该汇总值创建实时(每秒钟新值)图表,并且我必须使用一些数据分析软件(DAS)的绘图功能。假设这个软件可以使用多种数据 IO 访问方式,那么从 tcl 传递数据值的最佳方式是什么?例如,我可以将它写入文件,然后在 DAS 中读取文件,但在这种情况下,我想这将是访问打开文件甚至同步的问题。

我认为如果我可以从该 DAS 运行 tcl 脚本可能会更容易,但现在看起来这是不可能的,看起来必须从该系统特定软件启动脚本。

非常感谢任何帮助、提示等。

最好的问候 bLAZ

4

3 回答 3

3

@Vishwadeep:你想错了。Tk 支持调度一个任务在一些延迟后运行,而不是等待 1 个周期然后做某事。这使用完全相同的after命令,但是您给它提供了在延迟到期时运行的过程或脚本。当您考虑将多个此类阅读器链接在一起时,这两种模型之间的差异变得显着。因此,您应该使用类似的东西:

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

据我了解,假设“命令”是一个命令,它会产生电压值:因此可以使用 tk canvas 生成绘图,并且可以使用 exec 获取值

代码:

    set width 500
    set height 500
    canvas .c -width $width -height $height -background white
    pack .c

    set oldx 0
    set oldy 0
    while {1} {
        after 1000; # After 1 sec
        set newy 0
        catch {set newy [exec command]}; # setting the newy value, means voltage value from "cmd" which is a shell command
        .c create line $oldx $oldy [expr $oldx+1] $newy; # will draw a line from previous plot point to latest plot point
        incr oldx; # increasing x values means time be 1 sec
        set oldy $newy
        puts "Updating for $oldx sec"
        update
    }
于 2013-09-13T09:01:19.283 回答
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,这是列表的第二个元素。你必须GetDataHere用返回值的命令替换。

协议很简单:每行一个值,每秒一个新值。

于 2013-09-13T12:31:26.507 回答