美国国防部和一些商业领域中,部分应用程序需要低速率(低功耗)的无线通信。举例来说,如今大多数现代交通工具都随带胎压监测系统。
胎压传感器数据是如何从各个轮胎发送到车载嵌入式计算系统,并最终到达仪表板的呢?显然,传感器和仪表板的数据总线之间没有线路连接。因此,正如您所想象的,一定有某种机制从胎压传感器检索传感器数据。并且,此机制一定是无线的,并且可以长时间连续运作,毫无中断现象。
在本技术文章中,我们将探讨如何使用 Java ME 和 Sun SPOT 技术创建用于读取传感器数据的低带宽无线系统。下图显示了一个与 US quarter 有关的 SPOT。
下面列出了一些 Sun SPOT 规格。您将发现在这种新计算平台上创建和部署应用程序为何会使我如此激动:
Java ME CLDC 1.1 JVM (Squawk VM)
180 MHz 32 位处理器
512K RAM
4M 闪存
IEEE 802.15.4 无线传感器
3 轴加速度传感器
温度传感器
光传感器
具有 6 个模拟输入的模数转换器 (ADC)
2 个可程控开关
充电电池
注意:虽然 Sun SPOT 兼容 802.15.4 规范,但是它们并不完全兼容真正的 ZigBee 设备,因为它们没有实现 ZigBee 协议 中的上层协议。因为许多人对 ZigBee 感到陌生,所以我们将它与某些常用的标准无线通信协议做一个比较。下表比较了 WiFi、Bluetooth 和 ZigBee 。
|
WiFi |
Bluetooth |
ZigBee |
IEEE 规范 |
802.11b,g |
802.15.1 |
802.15.4 |
最大带宽 |
54 Mb/s |
3 Mb/s |
250 kb/s |
最大通信范围 |
300 ft. |
300 ft. |
914.40 cm. |
功耗率 |
小时 |
日 |
月/年 |
如您所见,ZigBee(或者任何其他 IEEE 802.15.4 衍生协议)是无线传感器应用程序的理想协议。这些应用程序以下列场景为代表,在这些场景中,建立到敏感传感器或传感器阵列(如胎压传感器)的连接是不切实际或不方便的。Sun SPOT SDK 包含 3 个 SPOT 设备。其中一个设备通过 USB 电缆连接到您的计算机上作为基站,而另外两个设备可以自由移动。
本技术文章将介绍两个功能完整的应用程序,第一个是基站应用程序,从第二个应用程序(移动无线 Sun SPOT)接收数据。在这个场景中,我不计划执行任何用于两个设备互相找到对方的发现机制。因为我已经知道基站和移动 SPOT 的 ZigBee 地址,所以我计划直接告诉双方对方的地址。因为 SPOT 有一个 CLDC JVM,所以我将使用通用连接框架 ( Generic Connection Framework, GCF),以便建立基站与移动 SPOT 的连接:
Connector.open("radiostream://0014.4F01.0000.1447:55");
如您所见,移动 SPOT 的无线地址是 0014.4F01.0000.1447。虽然在此应用程序中,我选择 55 作为端口号,但是您可以自由地选择 31~127 之间的任意数值作为您的应用程序的端口号。
下面是基站应用程序的完整代码,文件名为
HostReceiver.java
。它打开了一个到移动 SPOT 设备的无线连接,并从远程设备接收 10 个温度值。
package receiver;
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.DataInputStream;
import javax.microedition.io.InputConnection;
import com.sun.spot.util.*;
import java.io.*;
import javax.microedition.io.*;
public class HostReceiver {
/**
* Print out our radio address.
*/
public void run() throws IOException{
IEEEAddress zigbeeAddress = new IEEEAddress(Spot.getInstance().getRadioPolicyManager().getIEEEAddress());
System.out.println("The Host station Zigbee radio address = " + zigbeeAddress.asDottedHex());
StreamConnection streamConnection = (StreamConnection) Connector.open("radiostream://0014.4F01.0000.1447:55");
for(int i=0; i<10; i++){
DataInputStream data_input_stream = streamConnection.openDataInputStream();
double value = data_input_stream.readDouble();
System.out.println("The temperature is: " + value + "F");
data_input_stream.close();
Utils.sleep(3000);
}
streamConnection.close();
System.exit(0);
}
/**
* Start up the host application.
*
* @param args any command line arguments
*/
public static void main(String[] args) throws Exception {
HostReceiver app = new HostReceiver();
app.run();
}
}
下面是移动 SPOT 应用程序的代码,其使用它的温度传感器接收周围的温度。它将取样 10 次温度,并将数据发送到基站。此应用程序也做一些其他工作,打开外部的 LED,使其显示不同颜色,让操作员知道 SPOT 是否运作正常。所有代码都包含在文件 SpotSender.java
中。
package sender;
import com.sun.spot.peripheral.Spot;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
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 com.sun.spot.sensorboard.io.ITemperatureInput;
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import java.io.*;
import javax.microedition.io.*;
public class SpotSender extends MIDlet {
public StreamConnection streamConnection = null;
public ITemperatureInput temperatureSensor = null;
public IEEEAddress zigbeeAddress = null;
public SpotSender(){
try {
streamConnection = (StreamConnection) Connector.open("radiostream://0014.4F01.0000.1709:55");
temperatureSensor = EDemoBoard.getInstance().getADCTemperature();
zigbeeAddress = new IEEEAddress(Spot.getInstance().getRadioPolicyManager().getIEEEAddress());
System.out.println("Our radio address = " + zigbeeAddress.asDottedHex());
} catch (IOException e){
System.out.println("exception in constructor");
}
}
protected void startApp() throws MIDletStateChangeException {
// get a reference to the LED array
ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
// set LED2 to green
leds[2].setRGB(0,100,0);
for(int i=0; i<10; i++){
// turn all LEDs off
leds[2].setOff();
leds[3].setOff();
leds[4].setOff();
// turn LED2 on
leds[2].setOn();
Utils.sleep(250);
try{
DataOutputStream data_output_stream = streamConnection.openDataOutputStream();
data_output_stream.writeDouble(temperatureSensor.getFahrenheit());
data_output_stream.close();
// set the color to blue
leds[3].setRGB(0,0,100);
leds[3].setOn();
} catch (Exception e){
// set the color to red
leds[4].setRGB(100,0,0);
leds[4].setOn();
}
leds[2].setOff();
Utils.sleep(3000);
}
try{
streamConnection.close();
} catch (IOException e){
}
}
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
}
}
您可以自己部署和运行代码,这会发生什么呢?您将获得基站应用程序的输出结果,如下所示:
The Host station radio address = 0014.4F01.0000.1709
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.5F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.95F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.05000000000001F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.5F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.95F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.05000000000001F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.5F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.05000000000001F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.5F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55
[radiostream] Adding: Input from 0014.4F01.0000.1447 on port 55
The temperature is: 90.5F
[radiostream]Removing: Input from 0014.4F01.0000.1447 on port 55