假设在iSeismometer网站的一篇
博客文章中所讨论的设置下,有几个选项可供选择。
导入
第一个选项是使用外部程序来捕获数据包,然后使用
导入
将结果带入,例如:
Import["!someexternalprog", "Lines"]
哎呀,博客文章中提到的Python程序在这里无法很好地工作,因为它运行在必须手动终止的无限循环中。如果该程序被修改为在固定数量的数据包或时间限制后停止,则Import
方法才能起作用。
JLink
可以通过使用JLink在舒适的Mathematica环境中实现另一种方法。也许说我们仍然在Mathematica中有点牵强,因为相当数量的奇怪的Java代码与Mathematica代码混合在一起。尽管如此,它确实展示了随每个Mathematica副本一起附带的内置Java分发的实用性:
Needs["JLink`"]
LoadJavaClass["java.util.Arrays"];
ClearAll@ListenToISeismometer
ListenToISeismometer[port_] :=
JavaBlock@Module[{socket, packet, listen, record = Null, listening = True}
, packet = JavaNew["java.net.DatagramPacket", JavaNew["[B", 1024], 1024]
; listen[] :=
If[$Failed =!= Quiet[socket@receive[packet], Java::excptn]
, record =
JavaNew[
"java.lang.String"
, java`util`Arrays`copyOfRange @@ packet /@ {getData[], getOffset[], getLength[]}
]@toString[] // Sow
]
; Row[{Button["Stop", listening = False], Dynamic[record]}, " "] // PrintTemporary
; AbortProtect[
socket = JavaNew["java.net.DatagramSocket", port]
; socket@setSoTimeout[1000]
; Reap[While[listening, listen[]]; socket@close[]][[2, 1]]
]
]
为了使这个示例长度可控,有关异常处理、数据包解码等方面已经采取了一些捷径。
ListenToISeismometer
需要指定要监听的UDP端口号。让我们使用博客文章中相同的端口号10552:
In[33]:= data = ListenToISeismometer[10552];
![停止按钮](https://istack.dev59.com/JxbKB.webp)
该函数将监听该端口上的所有UDP事件,直到被告知停止。为此提供了一个按钮,每个数据包都会在旁边闪烁以表示接收到。
当按下按钮时,该函数将返回接收到的数据包列表:
In[34]:= data // Column
Out[34]= 1,83575.099,0.029,0.044,0.094
1,83575.781,0.056,0.033,0.099
1,83575.924,0.047,0.054,0.094
1,83575.613,0.096,0.092,0.057
1,83575.748,0.073,0.049,0.061
1,83575.577,0.008,0.089,0.020
...
JLink使这成为可能,但无法逃脱使用JLink需要掌握Java的事实。