[实验] 开发Sun SPOT基站应用
发表时间:2008-06-26 05:35:47一、预备知识
在一个典型的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上测量到的温度和亮度。
| 上一篇 | 下一篇 |
| 姓名: | |
| 评论: | |
|
请输入下面这首诗词的作者姓名。 白日依山尽,黄河入海流。 |
|
| 答案: | |
云与清风常拥有,
冰雪知音世难求。
击节纵歌相对笑,
案上诗书杯中酒。
2000.12.31 于 洛杉矶