奥运期间,禁止搬家

By , 2008年6月30日 8:17 下午

星耀马上就要离开中国了。他打电话给搬家公司,请他们来帮忙搬运一些家具。人家很客气的跟他说:对不起,由于奥运的关系,一直到9 月份为止都不能够搬家。

星耀哭笑不得,跟我们说:这奥运真是比双规还厉害呀,看来我是要被软禁在中国了。

这个鸡飞狗跳的奥运,真给我们的生活带来不少乐趣呢。

[实验] 在Sun SPOT上存取数据

By , 2008年6月28日 8:04 下午

一、预备知识

在一个典型的Sun SPOT应用中,目标端(移动端)Sun SPOT通常并不是实时地将所有采集到的传感器通过无线数据链发送给基站。以一个大地磁场监测的无线传感器网络应用为例,传感器采集到的数据可以分成如下几类:

1 与平时的监控数据没有什么差异,不值得保存或者是汇报的,当场丢弃处理;

2 与平时的监控数据有一些细微的差别,值得进一步研究,但是并不需要紧急汇报和响应,则存储到该节点自身的存储器上,等到数据存储到一定的量级后再一次性传输到基站上。所有数据都转移到基站上之后,将节点上的数据删除以释放存储空间。

3 与平时的监控书具有较大的差别,需要紧急汇报和响应,则通过无线数据链马上向基站报告异常情况,并且提高数据采集和汇报的频率。

Sun SPOT采用了Java ME中常见的Record Management Store (RMS)框架来管理应用程序的数据。RMS是一个简单的基于纪录的持久层框架,简单地讲,可以将一个Record Store想象成一个文件,将一条记录看成是一个文件里面的一行。RMS通过记录号(可以想象为行号)来定位和存取相关的纪录。在同一个MIDlet应用 程序中,可以创建和访问多个Record Store。

二、示范程序

在一个Sun SPOT应用中,可以通过如下方法来创建和访问Record Store。

导入相关类库:

import javax.microedition.rms.RecordStore;

import javax.microedition.rms.RecordStoreException;

创建一个RecordStore的实例rms,打开一个名为TEST的Record Store。如果该Record Store尚未存在,则创建这个Record Store。

RecordStore rms = RecordStore.openRecordStore(“TEST”, true);

创建一个数组inputData,这个数组是需要写入Record Store的数据:

byte[] inputData = new byte[]{12,13,14,15,16};

将这个数组作为一个记录写入Record Store,同时返回与这个数组相关的记录号recordId:

int recordId = rms.addRecord(inputData, 0, inputData.length);

创建一个数组outputData,将与指定记录号相对应的记录读入该数组:

byte[] outputData = rms.getRecord(recordId);

关闭该RecordStore:

rms.closeRecordStore();

下载示范程序RecordStoreDemo.zip

三、编程练习

编写一个Sun SPOT应用。目标端Sun SPOT以10 Hz的频率采集加速度传感器的信息,并且保存在Sun SPOT上。数据采集的时间为1 分钟,数据采集结束之后通过无线数据链将存储的数据发送给基站端,并且删除保存在目标端Sun SPOT的数据。

四、参考资料

RecordStore

[实验] 开发Sun SPOT基站应用

By , 2008年6月26日 5:35 上午

一、预备知识

在一个典型的Sun SPOT应用中,基站的作用是与远程的Sun SPOT进行通讯,接收远程Sun SPOT发送回来的信息,或者是向远程Sun SPOT发送指令以控制其行为。如下图所示,Host是一台通过USB数据线与一台作为基站(base station)的Sun SPOT相连接的计算机,基站又通过无线电与作为通讯目标(target)的Sun SPOT进行通讯。在基站与目标之间采用的通讯协议为IEEE 802.15.4。

任意一台Sun SPOT设备都可以作为基站使用。通常来说,大部分的Sun SPOT都被设置为非基站模式,因此您需要使用如下命令将其设置为基站模式:

ant selectbasestation

非常重要:当您执行了ant selectbasestation命令之后,您需要按一下该Sun SPOT上的控制按钮(在两个状态指示LED之间)。Sun SPOT在重新启动之后就会进入基站模式。

一 个完整的Sun SPOT应用通常包括两个部分,一个目标端(移动端)应用,另外一个是基站端(主机端)应用。目标端应用是MIDlet应用程序,它运行在作为通讯目标的 Sun SPOT上。基站端应用是一个Java SE应用程序,它运行在主机上(而不是作为基站的Sun SPOT上)。但是,基站端的Java SE应用程序可以通过Sun SPOT SDK中提供的类库访问作为基站的Sun SPOT,因此能够利用基站的无线数据链与目标端进行通讯。

用如下命令编译一个基站端应用:

ant host-compile

用如下命令运行一个基站端应用:

ant host-run

二、基站应用的基本框架

下面我们用一个简单的基站应用来介绍其基本框架:

/**
* 定义包名
*/

package org.sunspotworld.demo;

/**
* 导入必要的类库
*/

import com.sun.spot.peripheral.*;
import com.sun.spot.peripheral.radio.*;
import com.sun.spot.io.j2me.radio.*;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.util.IEEEAddress;
import java.io.*;
import javax.microedition.io.*;

/**
* 开始定义一个类,这个类就是一个简单的Sun SPOT基站应用
*/

public class SunSpotHostApplication {

/**
* run() 方法是这个简单的Sun SPOT基站应用需要完成的任务。
* 它获得本机的IEEE扩展Mac地址,并且将其打印出来。
*/
public void run()
{

/**
* 获得本机的IEEE扩展Mac地址
*/
IEEEAddress ourAddr = new IEEEAddress(Spot.getInstance().getRadioPolicyManager().getIEEEAddress());

/**
* 打印本机的IEEE扩展Mac地址
*/
System.out.println(“Our radio address = ” + ourAddr.asDottedHex());

/**
* 退出(执行完毕)
*/
System.exit(0);
}

/**
* main()方法是每一个Java SE应用都必须声明的方法。
* 它是一个Java SE应用的入口。
*/
public static void main(String[] args) throws Exception
{

/**
* 创建一个自身的事例
*/
SunSpotHostApplication app = new SunSpotHostApplication();

/**
* 调用run()方法
*/
app.run();
}

}

三、基站和目标之间的通讯

在上面的示范程序中,我们注意到基站应用可以获得基站的IEEE扩展Mac地址。这就意味着我们可以利用我们在Sun SPOT无线通讯专题中介绍过的几种通讯方法(例如radiostream, radiogram)来与目标Sun SPOT进行通讯。

下面是一个经过改进的Sun SPOT应用,该应用监听100端口接收到的所有数据并且将其打印到屏幕上:

/**
* 定义包名
*/

package org.sunspotworld.demo;

/**
* 导入必要的类库
*/

import com.sun.spot.peripheral.*;
import com.sun.spot.peripheral.radio.*;
import com.sun.spot.io.j2me.radio.*;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.util.IEEEAddress;
import java.io.*;
import javax.microedition.io.*;

/**
* 开始定义一个类,这个类就是一个简单的Sun SPOT基站应用
*/

public class SunSpotHostApplication {

/**
* run() 方法是这个范例Sun SPOT基站应用需要完成的任务。
* 它监听并打印100端口接收到的所有数据。
*/
public void run() {
/**
* 获得本机的IEEE扩展Mac地址
*/
IEEEAddress ourAddr = new IEEEAddress(Spot.getInstance().getRadioPolicyManager().getIEEEAddress());

/**
* 打印本机的IEEE扩展Mac地址
*/
System.out.println(“Our radio address = ” + ourAddr.asDottedHex());

/**
* 定义一些必要的类
* RadiogramConnection conn,使用RadiogramConnection进行连接
* Datagram dg_receive,发送过来的数据包
* String input_message, 数据包中提取出来数据
*/
RadiogramConnection conn;
Datagram dg_send, dg_receive;
String input_message;

try
{
/**
* 打开100端口,进行监听
*/
conn = (RadiogramConnection) Connector.open(“radiogram://:100”);

/**
* 进入一个无线循环
*/
while (true)
{
/**
* 构造一个新的Datagram对象,用来接收数据
*/
dg_receive = conn.newDatagram(conn.getMaximumLength());
/**
* 等待接收数据包
*/
conn.receive(dg_receive);
/**
* 接收到数据包之后,从中提取出文本信息
*/
input_message = dg_receive.readUTF();
/**
* 将文本信息打印出来,进入下一个循环。
*/
System.out.println(input_message);
}
} catch (IOException e)
{
}

}

/**
* main()方法是每一个Java SE应用都必须声明的方法。
* 它是一个Java SE应用的入口。
*/
public static void main(String[] args) throws Exception
{

/**
* 创建一个自身的事例
*/
SunSpotHostApplication app = new SunSpotHostApplication();

/**
* 调用run()方法
*/
app.run();
}

}

在目标端,我们可以写一个简单的应用,该应用以一定的频率采集XYZ三轴上的加速度以及其倾斜角,并且通过100端口将这些数据广播出去。

package org.sunspotworld;
import com.sun.spot.peripheral.Spot;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ITemperatureInput;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.peripheral.ISwitch;
import com.sun.spot.sensorboard.peripheral.ILightSensor;
import com.sun.spot.sensorboard.peripheral.LEDColor;

import com.sun.spot.peripheral.NoRouteException;
import com.sun.spot.peripheral.radio.IRadioPolicyManager;
import com.sun.spot.io.j2me.radiostream.*;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.util.*;

import java.io.*;
import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class StartApplication extends MIDlet {

/**
* 声明各种传感器,今后会用到
*/
private ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[0];
private ISwitch sw2 = EDemoBoard.getInstance().getSwitches()[1];
private ITriColorLED leds[] = EDemoBoard.getInstance().getLEDs();
private ILightSensor lightSensor = EDemoBoard.getInstance().getLightSensor();
private ITemperatureInput tempSensor = EDemoBoard.getInstance().getADCTemperature();
private IAccelerometer3D accel = EDemoBoard.getInstance().getAccelerometer();

/**
* starApp()方法启动一个Sun SPOT应用程序。
*/
protected void startApp() throws MIDletStateChangeException {

/**
* 启动一个线程,检测USB电缆是否被连接上。
*/
new BootloaderListener().start();

/**
* 获得本机的IEEE扩展Mac地址。
*/
IEEEAddress ourAddr = new IEEEAddress(Spot.getInstance().getRadioPolicyManager().getIEEEAddress());

/**
* 打印本机的IEEE扩展Mac地址。
*/
System.out.println(“Our radio address = ” + ourAddr.asDottedHex());

/**
* 声明程序中用到的对象
* RadiogramConnection — 通讯连接
* dg_send — 发送出去的数据包
* i — 计数器
*/
RadiogramConnection conn;
Datagram dg_send;
int i = 0;

try
{

/**
* 创建广播。
* 100是通讯双方约定的端口号。
*/
conn = (RadiogramConnection) Connector.open(“radiogram://broadcast:100”);

/*
* 声明必要的变量
* accel_X, accel_Y, accel_Z是XYZ三轴上的加速度
* tilt_X, tilt_Y, tilt_Z是XYZ三轴的倾斜角
* message是要发送出去的信息
*/
double accel_X, accel_Y, accel_Z;
double tilt_X, tilt_Y, tilt_Z;
String message;

/**
* 进入一个无限循环。
*/
while (true)
{

/**
* 获得XYZ三轴上的加速度和倾斜角
*/
accel_X = accel.getAccelX();
accel_Y = accel.getAccelY();
accel_Z = accel.getAccelZ();
tilt_X = accel.getTiltX();
tilt_Y = accel.getTiltY();
tilt_Z = accel.getTiltZ();

/**
* 构造将要发送出去的字符串
*/
message = ourAddr.asDottedHex() + “:” + accel_X + “:”+ accel_Y + “:” + accel_Z + “:” + tilt_X + “:” + tilt_Y + “:” + tilt_Z;

/**
* 创建用来发送数据的数据包。
*/
dg_send = conn.newDatagram(conn.getMaximumLength());

/**
* 将需要发送的内容写入需要发送的数据包。
*/
dg_send.writeUTF(message);

/**
* 发送数据包。
*/
conn.send(dg_send);

/**
* 休息三秒钟。进入下一个循环。
*/
Utils.sleep(3000);
}
} catch (IOException e)
{
System.out.println(“No route to the destination Sun SPOT.”);
}

}

protected void pauseApp() {
// This will never be called by the Squawk VM
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// Only called if startApp throws any exception other than MIDletStateChangeException
}
}

四、示范程序

下载HostDemo_Broadcast.zip ,解压缩之后有两个目录。一个是HostDemo,是基站端应用程序;另外一个是SendData,是目标段应用。

首先将目标端Sun SPOT连接到计算机上,进入SendData目录,编译、部署和运行:

ant jar-app
ant jar-deploy
ant run

将目标端Sun SPOT拔除,接上基站端Sun SPOT,进入HostDemo目录:

ant selectbasestation

按一下控制按钮重新启动Sun SPOT,这时候Sun SPOT就会进入基站模式。我们接下来编译和运行这个基站端应用:

ant host-compile
ant host-run

五、编程作业

编写一个完整的Sun SPOT应用,包括基站端和目标端两个部分。基站Sun SPOT和目标Sun SPOT之间使用radiostream协议来进行通讯,从而可靠地进行数据传输。数据传输的频率为1 Hz,传输的数据为目标Sun SPOT上测量到的温度和亮度。

如何使用Unix-Center.Net提供的IPS服务器

By , 2008年6月26日 1:56 上午

在OpenSolaris操作系统中,使用了一个称为映像包管理系统(Image Packaging System,IPS)的软件生命周期管理(安装,升级和删除)的框架。Unix-Center.Net于2008年6 月25日开始正式提供IPS服务。本IPS服务器所提供的软件包来源于OpenSolaris缺省的IPS服务器 pkg.opensolaris.org,并且定期与pkg.opensolaris.org保持同步(由相当的延迟)。本IPS服务器位于中国国内,有 公网和教育网的双网接入,访问速度应该比pkg.opensolaris.org快很多。该服务器的地址如下:

公网用户:http://pkg.unix-center.net:80/

教育网用户: http://pkg-edu.unix-center.net:80/

您可以在OpenSolaris 2008.05上使用如下命令来配置你的系统,从而使用Unix-Center.Net提供的IPS服务器:

成为超级用户

#su

添加Unix-Center.Net的IPS服务器,并且将其指定为缺省的IPS服务器

#pkg set-authority -P -O http://pkg.unix-center.net:80/ unix-center.net

教育网用户建议使用教育网专用的主机名:

# pkg set-authority -P -O http://pkg-edu.unix-center.net:80/ unix-center.net

更新软件列表:

# pkg refresh

安装OpenOffice:

# pkg install openoffice

太姥姥的手艺

By , 2008年6月21日 8:15 下午

清扬婉兮的太姥姥(我们家咪咪的奶奶),今年94岁了。 昨天我们一起到太姥姥家去给她祝寿,得以见识老人家二十年前的手艺。据说,这三件作品是太姥姥二十年前绣的,一直都藏在壁柜里面。

小时候清扬婉兮穿的衣服,有好多都是太姥姥亲手做的。 不但用料和商场里买来的完全不同,衣服上的小饰品都是太姥姥当年一针一线绣出来的。因为心疼重孙女的缘故,才慷慨拿出来缝到小人的衣服上。每次清扬婉兮穿上太姥姥做的衣服,都有好多人过来夸奖这衣服真是好看。

这两年太姥姥的眼睛不太好,做针线活比较吃力,但还经常惦记着给清扬婉兮买好看的花布。


Rock & Roll……

By , 2008年6月20日 12:51 上午

这一段录像也是在幼儿奥尔夫音乐培训班最后一节课上拍的。 汇报演出结束之后,大部分家长和孩子开始离开教室,但是清扬婉兮仍然恋恋不舍地跟管老师耍赖皮。仍然是用超小型的IXUS 75拍的,用Windows Media Maker将两段视频拼接在一起,总长度为1 分14秒。

点击上面的图片开始下载WMV格式的视频,大小只有8 MB。

汇报演出

By , 2008年6月19日 6:45 上午

在之前一个帖子《毕业了……》当中提到,幼儿奥尔夫音乐培训班的最后一节课是汇报演出。管慧丹老师带领孩子们表演了《奔跑的野马》。我用随身带的佳能IXUS 75拍了一些录像,觉得画面质量还不错,真的没想到这么小的数码相机也可以录出这样的效果。回家后用Windows Movie Maker编辑了一下,大幅度的缩小了尺寸。在这里贴出一个两分钟的片断,相信其他的家长也会喜欢上这样的培训班。

点击上面的图片开始下载WMV格式的视频,大小只有12 MB。

Life Is Changing

By , 2008年6月18日 1:10 上午

Sin-Yaw Wang made an announcement today that he is leaving Sun for an external opportunity. This is such an unexpected news that reminds me that life is always changing. Sin-Yaw Wang is a great leader with a helping heart. He is open minded, kind, and straight forward. As a versatile blogger, he maitains several blogs simultaneously, including NomadicMinds, Whiteboard Infinity (English), and Whiteboard Infinity (Chinese). It was very strange, but my first thought after reading his “opt out” message was whether his blogs on Sun’s web property would remain there after he departs.

Another collegue whom I have been working very closely during the past three years also decided to leave Sun. He did a great deal of great work in promoting Sun’s product and technology — especially OpenSolaris — in the academic space. His departure will be a significant lost for Sun’s technology outreach efforts in China. I will miss him a lot.

Yes, life is changing, constantly.

Updated: Now I believe that it is a wise decision to host my blog on my own domain domain. Nobody will work for a single employer for a life time, and it would be a great headache to migrate your blog every time you make a change in your career.

40%的进口税

By , 2008年6月16日 1:02 上午

经过20天的等待,同事从美国快递给我的Sun SPOT终于到了。一件快递,5 月28日从美国发出,6 月2 日到达北京,6 月16日才送到我的手中。虽说一切为了奥运,可是这速度也太慢了一点。

以前从来都没有注意过进口税,那是因为自己没有亲自交过,这回总算是领教了。同事在联邦快递的运单上写的保价金额为790 美元,中国海关委托联邦快递向我收取的进口税为人民币2221元。自己拿计算器扒拉了一下,40%,哇~~~

不管怎么说,东西到了就好。好几个学校的老师等着用呢。

毕业了……

By , 2008年6月15日 7:06 下午

清扬婉兮从幼儿园退学之后,我们每周六下午带她到音乐学院上一节幼儿奥尔夫音乐培训班,每次一个小时。这节课也是清扬婉兮唯一的一个集体活动,可以跟很多小朋友在一起玩耍。

清扬婉兮并不是一个喜欢上课的孩子,但是她非常喜欢奥尔夫班的老师。上课的时候,她就坐在地上(老师、家长和孩子都是坐在地毯上的)一直看老师。班上所有的孩子都差不多三岁左右,模仿能力和注意力都非常有限。老师教孩子们做动作的时候,很多家长都会手把手地带着孩子做,不过我们很少这么做 -- 我们觉得如果孩子没有兴趣,机械的模仿是没有意义的。等到老师让大家手拉手站成一个圈子的时候,清扬婉兮立刻就精神振奋,抢先一步冲过去拉住老师的手,紧紧地抓住不放,仿佛刚才长时间的沉默都是为了这一短暂的爆发积攒力量。老师讲课的时候,清扬婉兮也经常尝试用说话或者是做小动作的方法来吸引老师的注意力,而老师总是很柔和地制止她继续表演下去。回到家里之后,清扬婉兮会经常问我们:“今天到星期六了吗?今天可以去奥尔夫了吗?”从某种意义上来讲,清扬婉兮每天都惦记着周末要去上奥尔夫班,其实是想着去亲近她所喜欢的老师。

一个人一辈子会遇到很多老师。而遇到一个好老师的概率,就象是从河流里筛出金砂一样。清扬婉兮这么小就能够遇到一位让她喜欢的老师,不能不说是她的幸运。

不过说清扬婉兮对奥尔夫班上所教的东西不感兴趣并不公平,只是由于天性好动的原因,她不习惯于集中注意力安静地听讲而已。在回家的路上,或者是在睡觉之前,她就会一个人“复习”白天学过的内容,我甚至曾经听到她在做梦的时候唱歌。清扬婉兮喜欢大声唱歌,不管是在家里还是公共场合。在她看来,歌就是要大声唱出来的。而我们由于已经长大的关系,竟沦落到只能够在没人的地方甚至是洗澡间里大声唱歌了。

这个星期六上了最后一节课,也就是孩子们的汇报演出。管慧丹老师就象是森林里的女王,指挥着一群调皮的精灵。他们欢呼着,喧闹着,敲击着,尽情地释放无穷无尽的能量。我用手里的佳能IXUS 75拍了一些录像,画面质量还可以接受,不过由于没有三脚架的关系画面有点抖动(用手捧着相机拍的),稍后会整理一下贴出来。在室内这台微型相机拍摄的照片质量很差,如果把家里那台Nikon D50带来就好了。

汇报演出结束之后,清扬婉兮跟管老师在地上打滚玩。另外一位孩子的家长帮我们拍了下面两张照片,并且通过电子邮件发送给我们。因为过于将注意力集中在清扬婉兮身上的原因,我竟然忘记了询问他和他孩子的名字,真的是抱歉的很。还好现在已经有了他的电子邮件地址,可以向他表示感谢,并且交流更多的问题。

Panorama Theme by Themocracy