Cooja 中自定义 Java Mote 使用 Collect-View
来源:互联网 发布:网络视频广告收入 编辑:程序博客网 时间:2024/05/22 04:24
Cooja 中自定义 Java Mote 使用 Collect-View
受到网上一文的启发。可知 Collect-View中tools/collect-view/src/contiki/collect/ 下的三个类SensorInfo.java、SensorData.java、CollectServer.java 极为重要。经过分析我们知道节点的数据是保存在一个整型数组(如 int[] Value = new int[30] 必须是30,分析SensorData.java 可知)中, SensorInfo 是一个接口,它规定了一个整型数组中每个索引位置的意义,如 Value[0]=30 (必须是30), Value[4] 是一个节点ID的数值Value[1~2]是该组数据更新的时间戳等。
实现原理:节点将 Value[30] 以字符串形式写到一个文件上(但这个字符串前部还需要加上一个系统时间的字符串,分析SensorData.java可知,格式如下图1)。我们可以操作打开文件,读取这一行字符串,用 CollectServer 下的 handleIncomingData(long systemTime, String line) 进行解析,该方法的作用是根据字符串生成 SensorData 对象,并显示数据。
图1:
根据我的实验举例:
首先,我要说清楚的是我定义了 AbstractMote 抽象类,并定义了 Mote 和 Sink 类继承于 AbstractMote,分别代表仿真实验中的普通节点和 Sink 节点。使用 Collect-View 插件收集数据的思想是,实验中所有节点将自身的数据按要求写到一个文件中,再用 Collect-View 对象来进行读取并显示。
我在 AbstractMote 类中添加了以下代码(可见,我将数据写在了 SensorDataFile.txt 文件)
public int[] value = new int[30]; //用于保存节点的信息数据 /** * 更新传感器数据数组 * @param index * @param value */ public void updateSensorData() { //SensorData中 this.nodeTime = ((values[TIMESTAMP1] << 16) + values[TIMESTAMP2]) * 1000L; this.value[SensorInfo.DATA_LEN] = SensorInfo.VALUES_COUNT; //格式要求 this.value[SensorInfo.NODE_ID] = this.addr.intValue(); this.value[SensorInfo.NUM_NEIGHBORS] = this.neighbors_number; this.value[SensorInfo.BEACON_INTERVAL] = this.cnt_beacon_max; this.value[SensorInfo.BATTERY_INDICATOR] = (int) this.battery.getBatteryLevel(); this.value[SensorInfo.TIMESTAMP1] = ((int)(System.currentTimeMillis()/1000L)>>16);//vaule中是以秒为单位 this.value[SensorInfo.TIMESTAMP2] = ((int)(System.currentTimeMillis()/1000L)); } /** * 传感器数据数组转换为String (前面多加一个系统时间) * @return */ public String sensorDataToString() { StringBuilder sb = new StringBuilder(); sb.append(System.currentTimeMillis()).append(' '); for(int i=0; i< value.length; i++) { sb.append(Integer.toString(value[i])).append(' '); } return sb.toString().trim(); } /** * 将String写入文件 * @param line */ public void writeSensorData(String line) { File file = new File("SensorDataFile.txt"); BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(file, true)); out.write(line); out.newLine(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 周期性调度 */ public void updateSensorDataTask() { this.updateSensorData(); String line = this.sensorDataToString(); this.writeSensorData(line); }
节点周期性调度 updateSensorDataTask() 进行一次数据的更新显示,调度的时间根据自身要求设置,它是节点更新数据到 Collect-View 的时间。具体过程首先 updateSensorData() 对 value[] 数组中的数组进行更新,sensorDataToString() 将数组转化为加上一个系统时间的字符串,最后 writeSensorData() 将其写到文件上。
数据写到了文件上,那么接下来就是读取数据了。接下来是读取过程:(不断的读,开线程),我在这里自定义一个类 CollectInfo 来完成此工作。由于读取到的字符串需要 CollectServer 对象来进行解析,所以定义了一个有参的构造函数。代码中有一个睡眠操作,这个可以根据需要设置睡眠的时间,它决定了 Collect-View 的刷新周期。 CollectInfo 类如下:
public class CollectInfo implements Runnable { private CollectServer collectServer; public CollectInfo(CollectServer collectServer) { this.collectServer = collectServer; } @Override public void run() { while (true) { File file = new File("SensorDataFile.txt"); if (file.exists() && file.canRead()) { String line; BufferedReader in = null; try { in = new BufferedReader(new FileReader(file)); try { while ((line = in.readLine()) != null) { this.collectServer.handleIncomingData(System.currentTimeMillis(), line); } in.close(); file.delete(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } } try { Thread.currentThread().sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
在我的实验中,我是用 Sink 节点来开启收集数据的图形化界面的,于是我在 Sink 节点的初始化函数中,添加了下列代码
this.collectServer = new CollectServer(); this.collectServer.start();//启动收集数据的界面 this.collectInfo = new CollectInfo(this.collectServer); new Thread(this.collectInfo).start();//开始收集数据
但这里有一点要注意!! CollectServer 中只有一个 start(SerialConnecction connection) 的启动函数,形参是 Collect-View 中实现的接口类,因为我这里没有用到,所以我在 CollectServer 中重载了一个无参 start() 启动函数,只添加启动的语句。代码如下:
/** * 无参重载函数 * 用于启动收集数据的图形化界面 */ public void start() { if (hasStarted) { throw new IllegalStateException("already started"); } hasStarted = true; SwingUtilities.invokeLater(new Runnable() { public void run() { window.setVisible(true); } }); }
实验结果:由上述代码中 updateSensorData() 可知我关注的节点信息,其中有两个是节点邻居数和电量信息。进行实验结果如下:
本人学生,能力有限,花了三天做了这个小实验,匆忙写下这博客做为备忘的同时也与大家分享。有分析不到之处望大家谅解与指正,谢谢!
- Cooja 中自定义 Java Mote 使用 Collect-View
- Cooja中有关collect-view插件
- Collect View
- Android中使用自定义View
- 在自定义View中使用自定义属性
- 在cooja上使用collectview
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- 如何在ios中使用自定义view
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- Android中自定义View的MeasureSpec使用
- android自定义View中onMeasure的使用
- Android中自定义View的MeasureSpec使用
- 多线程应用于自动化测试
- 关键字static
- 写标流程学习总结
- 获得每个用户的最后一条记录
- 使用copy函数输出vector中的内容
- Cooja 中自定义 Java Mote 使用 Collect-View
- 使用POTEUS软件来进行模拟仿真 8086汇编语言花式跑马灯课程设计及代码
- jquery 全选、反选、即点即改
- redis3.0.7源码阅读(一)源码文件
- Good Bye 2016D. New Year and Fireworks(dfs)
- Spring对象生命周期控制
- Mybatis入门例子(本文章转载自博主AndyChenzy,如需转载注明转载博主)
- 生物演示攻击
- 对CloseHandle用法的理解