Tcl 传递更改的参数值的方法。文件还是。。。?

Tcl 传递更改的参数值的方法。文件还是。。。?,tcl,Tcl,我是tcl的不速之客,但我收到了使用tcl的相当复杂的系统(硬件和软件),我必须做一件事。这个硬件有我可以在tcl脚本中读取的接口。例如,我可以发送命令读取某个电压电平,硬件应以轮询值响应(AFAIK,它是带有工程值、原始值等的tcl列表) 我需要做的是用合并的值创建实时(每秒钟一个新值)图,我必须使用一些数据分析软件(DAS)的绘图功能。假设此软件可以使用多种数据IO访问方式,那么从tcl传递数据值的最佳方式是什么?例如,我可以将其写入文件,然后在DAS中读取文件,但在这种情况下,我认为访问打

我是tcl的不速之客,但我收到了使用tcl的相当复杂的系统(硬件和软件),我必须做一件事。这个硬件有我可以在tcl脚本中读取的接口。例如,我可以发送命令读取某个电压电平,硬件应以轮询值响应(AFAIK,它是带有工程值、原始值等的tcl列表)

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

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

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

致意
bLAZ

据我所知,假设“command”是一个命令,它会产生电压值: 因此,可以使用tk画布生成绘图,并使用exec获取值

代码:


据我所知,假设“command”是一个命令,它产生电压值: 因此,可以使用tk画布生成绘图,并使用exec获取值

代码:


@维什瓦迪普:你的想法是错误的。Tk不支持等待一段时间然后再做一些事情,而是支持将任务安排在延迟后运行。这使用了完全相同的
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
进行调查,当通道上的数据可用时,它将引发一个事件来调用一个过程。

@Vishwadeep:您的想法是错误的。Tk不支持等待一段时间然后再做一些事情,而是支持将任务安排在延迟后运行。这使用了完全相同的
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
进行调查,当通道上的数据可用时,它将引发一个事件来调用一个过程。

这里是一种基于套接字的方法:

# 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_客户端(如果不应该,只需
关闭$sock

您必须自己找出所需数据的索引,我使用了
1
,这是列表中的第二个元素。您必须用返回值的命令替换
GetDataHere


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

这里是一种基于套接字的方法:

# 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_客户端(如果不应该,只需
关闭$sock

您必须自己找出所需数据的索引,我使用了
1
,这是列表中的第二个元素。您必须用返回值的命令替换
GetDataHere


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

如果命令返回的值很复杂,则需要相应地解析信息。这种方法是错误的。您会一直阻塞GUI,并且GUI没有响应。我建议使用一种基于事件的方法,在1000 updatePlot之后使用
,它看起来不错,Tk似乎很强大,但可能还不够。另外,还必须在该DAS中计算另一个数据,并在GUI中显示。有特定的工具包和过程,所以我不能使用Tk图。这就是我在那里传递值的原因。但是谢谢你的想法。@JohannesKuhn在我的思想方法中可以坚持1秒,但只需添加到你的观点,bLAZ你可以继续将你的值附加到任何列表变量中,当每个用户点击plot时。可以使用最新值更新绘图。它不会显得毫无反应。命令:bind.c{UpdatePlotFunction}。。。。阻塞GUI并不是一个很大的障碍,有很多方法可以在冻结时从画布中删除绑定,并在解冻后重建绑定即使每99毫秒更新一次GUI也不够好。(是的,我知道