奥运期间,禁止搬家

By , June 30, 2008 8:17 pm

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

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

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

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

By , June 28, 2008 8:04 pm

一、预备知识

在一个典型的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 , June 26, 2008 5:35 am

一、预备知识

在一个典型的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 , June 26, 2008 1:56 am

在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 , June 21, 2008 8:15 pm

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

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

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


Panorama Theme by Themocracy