泽泽的歌

By , August 31, 2004 5:54 am

山歌
http://scms.whedu.net/feeling/8.mp3
词:王泽 曲:王泽  演唱:王泽


花儿花儿,开了 鸟儿鸟儿,唱歌了
春天到了,回声响了
慢慢地走啊走啊 到哪里去啊
随着溪流走啊走啊 沿着山路走啊走啊
口琴在悠悠,流年在水中
他们说年少的往事 山谷回响潮湿
春雨低吟未完的诗 年华已逝

一棵叫Feeling的植物
http://scms.whedu.net/feeling/3.mp3

曲:王泽 演唱:王泽 制作人:侯钧 编曲:孟可
MIDI工程:戴劲松 录音、混音:顾评


朋友,走的时候 留给我一个礼物
那是一棵叫做Feeling的植物
我知道他的一路
都曾有它的相处
他的成长带它一起生长
它的生长支撑他的脚步

它喜欢我心里面的土壤和阳光
偶尔的降雨能使它茁壮
所以它在冬天静静等待一双美丽的翅膀
它在雨天静静接受失败的漫长

它说你看你有一些总有一天要实现的梦想
你有一年四季可以喜怒哀乐心里有种下Feeling的地方
希望它能长成一棵漂亮的树
一棵漂亮的绿色植物
一棵飞舞的树 可以让我的一路
都有它的帮助 再不怕变的麻木
变得庸庸碌碌

航行
http://scms.whedu.net/zhijue/3.mp3

词:王泽  曲:王泽  演唱:王泽


我的心啊 有一片云 飘啊飘啊
漂泊不定 我的心啊 很少下雨
我总用快乐把它挂在天际 我的船啊
不停的划啊 一直到天边 找不到家

我的船啊 轻轻的摇啊 你知道我
什么也不怕 我把春天全都挂在桅杆
让它飘扬 让大海看见
我把阳光全都写在脸上 让它灿烂
让蓝天看见


心愿
http://scms.whedu.net/zhijue/8.mp3

词:王泽  曲:王泽  演唱:王泽&杨颖


湖水是你的眼神 梦想满天星辰
心情是一个传说 亘古不变地等候
成长是一扇树叶的门
童年有一群亲爱的人
春天是一段路程 沧海桑田的拥有

那些我爱的人 那些离逝的风
那些永远的誓言一遍一遍 

那些爱我的人  那些沉淀的泪
那些永远的誓言一遍一遍

我们都曾有过一张天真而忧伤的脸
手握阳光我们望着遥远
轻轻的一天天一年又一年
长大间我们是否还会再唱起 心愿
长大间我们是否还会再唱起 心愿

 

基于Java的GPS接收机解析器

By , August 31, 2004 5:17 am

[摘要]本文介绍了一个基于Java的GPS 接收机解析器。这个Java类通过解析标准GPS接收机的输出信号,能够为导航与控制系统提供GPS 时钟、经度、纬度、高程等一系列信息。本类库使用标准Java语言编写,不需要任何第三方通讯类库(包括Sun 公司的Java通讯API )的支持,稍加修改即可被广泛应用在各种便携式设备和嵌入式系统中。

[介绍]

全球定位系统 (Global Position System,简称GPS )是由美国研制的导航、授时和定位系统。该系统包括空中卫星、地面跟踪监测站、地面卫星数据注入站、地面数据处理中心和数据通讯网络等部分。这个系统通过 24颗地球同步卫星全天候向地面发送授时和定位信号,其中高精度的信号仅供美国军方和北约盟军使用,普通用户只能够接收和解析低经度的民用信号。如果对接 收到的民用信号进行差分处理,也可以得到精度很高的定位数据。目前一般的差分GPS 接收机都可以得到1 米精度的定位数据,在欧美市场上已经出现了厘米级的差分GPS 接收机。普通用户只需购买GPS 接收机,就可享受免费的导航、授时和定位服务。目前全球定位系统技术在农业、林业、水利、交通、航空、测绘、安全防范、军事、电力、通讯、城市管理等领域 都有广泛应用。

在上述所述应用领域中,GPS 接收机通常是某些便携式设备或者是嵌入式系统的外接输入设备。一般的GPS 接收机均通过串行通讯口主动向主机发送数据,其通讯参数为4800(波特率),8(数据位),1(停止位),0(奇偶校验位)。 由于 Java语言的平台无关性,很多基于便携式设备和嵌入式系统的应用程序都采用Java 语言进行开发。因此,一个基于标准Java语言的GPS 接收机解析器,无疑具有广泛的应用前景。

本文所介绍的基于Java的GPS 接收机解析器从标准GPS 接收机的GGA 输出信息中解析标准时钟(Universal Time Coordinate, UTC)、纬度(Latitude)、经度(Longitude )和高程(Altitude)等基本授时和定位信息。根据美国海军电子设备标准接口规定,该信息包含标准时间、经纬度、高程等数据,每个数据之间用逗号分 隔,以一个回车符号结束,一般格式如下:

$–GGA,标准时间,纬度,南北,经度,东西,信号质量,卫星总数,水平精度,高程,米,地理间隔,米,差分数据龄期,差分基准站ID*hh

$–GGA — GGA 信息标示符,根据接收机的不同,该标示符中的第二和 第三个字节会有所不同。
标准时间 — 一个浮点数,数据格式hhmmss.ss。
纬度 — 数据格式ddmm.mm,其中dd为度(整数,0 到90);mm.mm为 分(浮点数,0 到60)。
南北 — 南北半球标示符号,一个字节,S 为南半球,N 为北半球。
经度 — 数据格式dddmm.mm,其中ddd为度(整数,0到180);mm.mm 为分(浮点数,0 到60)。
东西 — 东西半球标示符号,一个字节,E 为东半球,W 为西半球。
信号质量 — 一个整数,从0 到8。
卫星总数 — 一个整数,从0 到24。
水平精度 — 一个浮点数。
高程 — 该地点在平均海平面以上的高程,一个浮点数。
米 — 长度单位标示符,一个字节,M。
地理间隔 — WGS-84地球椭球表面与平均海平面表面之间的距离,一个浮 点数。
米 — 长度单位标示符,一个字节,M。
差分数据龄期 — 上一次SC-104标定到当前的总秒数,一个浮点数。
查分基准站ID — 一个整数,从0000到1023。
除 了GGA 信息以外,一般的GPS 接收机还会输出其他类型的信息,例如AAM 信息,ACK 信息,GNS 信息等等。本文所介绍的Java类库持续的监听GPS 接收机所在的串行通讯口,从其输出信息中截获GGA 信息并进行解析,从而获得当前的时间和定位信息。本类库包括三个Java模块以及一组测试数据:

GPS 数据模块 — 实时保存当前数据(GpsInfo.java)。
GPS 接收机模块 — 供外部程序调用(GpsReceiver.java)。
数据接收与解析模块 — 接收与解析GPS 信息(GpsParser.java)。
测试模块 — 功能测试与范例(TestGps.java)。
测试数据 — 一组实际GPS 测量数据(gps.dat)。
[GPS 数据模块]

GPS 数据模块用来保存经过解析的授时与定位数据,同时提供访问与更新这些数据的方法。数据接收与解析模块通过数据更新方法SetXyz()实时更新授时与定位 数据,用户应用程序通过数据访问方法GetXyz()使用授时与定位数据。考虑到可能存在多个应用程序(线程)同时对GPS 数据进行修改的情况,所有的数据更新方法都利用synchronized关键字和notifyAll() 方法实现了数据同步。在这个类中包含的数据访问与更新方法比较多,部分列举如下:

数据访问方法:

public float GetTime()
此方法返回当前标准时间,其返回值是一个浮点数,数据格式hhmmss.ss。

public float GetLatitude()
此方法返回当前纬度信息,数据格式ddmm.mm,其中dd为度(整数,0 到90); mm.mm为分(浮点数,0 到60)。

public String GetNS()
此方法返回南北半球标示符号,一个字节,S 为南半球,N 为北半球。

public float GetLongitude()
此方法返回当前经度信息,数据格式dddmm.mm,其中ddd为度(整数,0到180) ;mm.mm为分(浮点数,0 到60)。

public String GetEW()
此方法返回东西半球标示符号,一个字节,E 为东半球,W 为西半球。

public float GetAltitude()
此方法返回当前平均海平面以上高程,一个浮点数。

数据更新方法:

public void SetTime(float time)
此方法更新当前标准时间,输入参数是一个浮点数,数据格式hhmmss.ss。

public void SetLatitude(float latitude)
此方法更新当前纬度信息,参数格式ddmm.mm,其中dd为度(整数,0 到90); mm.mm为分(浮点数,0 到60)。

public void SetNS(String ns)
此方法更新南北半球标示符号,一个字节,S 为南半球,N 为北半球。

public void SetLongitude(float longitude)
此方法更新当前经度信息,参数格式dddmm.mm,其中ddd为度(整数,0到180) ;mm.mm为分(浮点数,0 到60)。

public void SetEW(String ew)
此方法更新东西半球标示符号,一个字节,E 为东半球,W 为西半球。

public void SetAltitude(float altitude)
此方法更新当前平均海平面以上高程,输入参数是一个浮点数。

[GPS 接收机模块]

GPS 接收接模块是本类库于其他应用程序的接口,本模块为其他应用程序提供了连接、启动、切断GPS 接收机以及实时查询GPS 数据的方法。具体介绍如下:

构造方法:

public GpsReceiver(String GpsDevice, int Factor)
public GpsReceiver(String GpsDevice, int Factor, boolean Record)

其中:

GpsDevice — 即将使用的GPS 设备名称。如果GPS 接收机与计算机的串口COM1 或者是COM2相连接,则使用”COM1″或者是”COM2″作为设备名称, 以此类推;如果使用GPS 数据文件代替GPS 接收机的输入,则使 用该文件名作为设备名称,例如”gps.dat”。

Factor — 如果使用GPS 数据文件代替GPS 接收机的输入,则可以利用此变 量制定一个加速系数,用于快速回放等功能。普通GPS 接收机每 秒钟更新一次数据,如果指定加速系数为5 ,则每秒钟回放5 秒 钟的实际测量数据。如果从GPS 接收机接收数据,则需要将该参 数设定为0 。

Record — 如果使用了GPS 接收机,则可以通过将该参数设定为true来记录 GPS 接收机的输出数据。这些数据可以在程序测试中模拟GPS 接 收机的输入。

操作方法:

public void StartReceiver()
此方法启动与GPS 接收机的连接,并且开始更新授时与定位数据。

public void StopReceiver()
此方法停止更新授时与定位数据,并且切断与GPS 接收机的连接。

public GpsInfo GetGpsData()
此方法返回当前的授时与定位数据。

用 户在使用本类库的时候,通常是先声明一个GpsReceiver 对象,然后利用上述StartReceiver() 方法启动与GPS 接收机的连接并且开始接收与解析授时与定位信息。当用户不再需要使用来自GPS 接收机的信息时,可以利用StopReceiver()方法切断与GPS 接收机的连接并且释放所占用的系统资源。

[数据接收与解析模块]

数 据接收与解析模块是本类库的核心部分,这个模块负责监听GPS 设备输出的信号,从中截获并解析GGA 信息,从而得到最新的授时与定位数据。该模块可以使用实时和模拟两种方式工作,在实时模式下使用GPS 接收机作为输入设备,在模拟模式下使用GPS 数据文件模拟GPS 接收机的输入。此外,数据接收与解析模块还能够将GPS 接收机的输出数据保存到数据文件中供程序测试等使用。因此,数据接收与解析模块的构造方法与GPS 接收机模块的构造方法是类似的。

构造方法:

public GpsParser(String GpsDevice, int Factor, boolean Record, GpsInfo Info)

其中:

GpsDevice — 即将使用的GPS 设备名称。如果GPS 接收机与计算机的串口COM1 或者是COM2相连接,则使用”COM1″或者是”COM2″作为设备名称, 以此类推;如果使用GPS 数据文件代替GPS 接收机的输入,则使 用该文件名作为设备名称,例如”gps.dat”。

Factor — 如果使用GPS 数据文件代替GPS 接收机的输入,则可以利用此变 量制定一个加速系数,用于快速回放等功能。普通GPS 接收机每 秒钟更新一次数据,如果指定加速系数为5 ,则每秒钟回放5 秒 钟的实际测量数据。如果从GPS 接收机接收数据,则需要将该参 数设定为0 。

Record — 如果使用了GPS 接收机,则可以通过将该参数设定为true来记录 GPS 接收机的输出数据。这些数据可以在程序测试中模拟GPS 接 收机的输入。

Info — 用来保存授时与定位信息的GPS 数据对象。

数 据接收与解析模块的核心部分是一个线程,该线程被设计成一个内置类,这样的设计是的外部程序能够通过该类自定义的start() 和stop()方法来启动和终止该线程。在start() 方法中将一个名为DevOn 的逻辑变量设置为真并且启动数据接收与解析线程,在stop()方法中则将DevOn 设置为假。数据接收与解析线程在运行过程中不断监测DevOn 的值,如果DevOn 为假,则终止自身的执行。这个设计避免了已经不鼓励使用的(deprecated)的stop()方法来强制终止线程的执行,从而保证了该线程的安全终 止。

在数据接收与解析模块中把GPS 输入设备统一当作文件进行处理,因为大多数的操作系统均将串行端口设置为系统保留文件,应用程序只需要对该文件进行读写即可以通过串行端口与外界设备进行 通讯。一个GPS 接收机解析器只需要从串行端口实时读取数据而并不需要向GPS 接收机发送控制指令,使用标准文件输入函数来读取GPS 接收机的输入信号,完全能够满足功能上的要求。这样的设计使得数据接收与解析模块在实时模式和模拟模式下都能够使用同样的数据接收与解析程序,大大的简化 了整个程序的结构。此外,利用标准文件输入函数来对GPS 接收机进行操作,避免了在类库中使用例如javax.comm等第三方通讯API ,大大的提高了本类库的可移植性。

由于GPS 接收机的每一条信息均以回车换行符号结束,在数据接收与解析模块中使用了BufferedReader来读取GPS 接收机的输入信息。GPS 接收机的所有输入信号,首先被系统存放在一个缓冲区里面。数据接收与解析模块利用readLine()方法每次从该缓冲区里面读取一行数据,如果该行数据 包含GGA 数据标示符,则利用该数据解析授时与定位信息,反之则将该行数据舍弃继续读取下一行数据进行判断和处理。

由于普通GPS 接收机的数据更新频率为1 秒,在模拟模式下,数据接收与解析模块每读取到一条GGA 数据就暂停1 秒钟,从而模拟GPS 接收机的输入。如果用户指定了一个大于1 的加速系数,则根据加速系数计算暂停的时间,例如在加速系数为5 的情况下暂停时间为200 毫秒,因此回放模拟的速度相当于实际速度的5 倍。这个功能在耗时较长的程序测试中非常有用。考虑到一般应用程序所能够获得的时钟信号的精度不是很高的缘故,我们不推荐使用大于50的加速系数。

此外,数据接收与解析模块还提供了数据记录功能。利用数据记录功能能够将实测到GPS 信号保存到一个数据文件里面供回放和测试使用。该功能自动产生一个扩展名为.gps的数据文件,主文件名根据当时的系统时间自动生成,在通常的情况下不会发生数据覆盖的问题。

[程序测试]

在 本类库中提供了一个测试程序和一组测试数据。利用这个程序和数据用户可以使用实时和模拟两种方式对本类库进行测试,也可以在这个测试程序的基础上开发自己 的应用程序。测试环境包括多种版本的Windows 95/98/2000操作系统,四个不同型号的差分GPS 接收机,两个常规Java虚拟机以及两个嵌入式Java虚拟机。测试结果表明,本类库在以上不同条件的各种组合下均能够利用实时和模拟两种模式正常工作。

[结论]

本文设计和实现了一个基于Java的GPS 接收机解析器,全面测试结果表明,这个GPS 接收机解析器能够实现如下功能:

(1) 在实时模式下,从GPS 接收机接收与解析授时与定位数据。

(2) 在模拟模式下,利用GPS 数据文件回放授时与定位数据。用户可以通过设 定一个加速系数来改变数据回访的速度。

(3) 能够将实测到GPS 信号保存到一个数据文件里面供回放和测试使用。

(4) 本类库不需要任何第三方通讯类库(包括Sun 公司的Java通讯API )的支 持,稍加修改即可被广泛应用在各种便携式设备和嵌入式系统中。

[其他]

很早的一篇文章了,大概是2001年写的,很多东西已经跟不上形式了,放在这里做个记录吧。

Access USB devices from Java applications

By , August 30, 2004 5:15 am

Introduction 

The Java platform has traditionally prided itself on its platform independence. While that independence has many benefits, it makes the process of writing Java applications that interact with hardware quite tricky. In this article, research scientist Qingye Jiang examines two projects that are making the process easier by providing APIs through which Java applications can make use of USB devices. While both projects are still in embryo form, both show promise and are already serving as the foundations of some real-world applications.

The first version of the Universal Serial Bus (USB) specification was released in January 1996. Because of its low cost, high data-transfer rate, ease of use, and flexibility, USB has gained wide acceptance in the computer industry. Today, many peripherals and devices connect to computers through USB interfaces. Currently, most general-purpose operating systems provide support for USB devices, and it is relatively easy to develop applications in C or C++ that access such peripherals. However, the Java programming language by design provides very little support for hardware access, so writing Java applications that interact with USB devices has proved quite difficult.

Efforts to provide access to USB devices in the Java language were initiated in 1999 by Dan Streetman at IBM. In 2001, his project was accepted as a candidate extended standard of the Java language through the Java Specification Request (JSR) process. The project is now called JSR-80 and has been officially assigned the Java package javax.usb. Meanwhile, in June 2000, Mojo Jojo and David Brownell started the jUSB project at SourceForge. Both of these projects have since produced usable packages for Linux developers, although neither is close to perfect. Both projects also have begun attempts to provide access to USB devices for Java applications on other operating systems, though usable packages have not yet emerged from either. (See Resources for references to these and other projects discussed in this article.)

In this article, you’ll get a brief introduction to the jUSB and JSR-80 projects; first, however, we’ll take a look at the nuts and bolts of the USB protocol, so that you can understand how both of those projects interact with USB devices. We’ll also offer code snippets to show how you’d use both projects’ APIs to access USB devices.

An introduction to USB


In 1994, an alliance of four industrial partners (Compaq, Intel, Microsoft, and NEC) started specifying the USB protocol. The original goal of the protocol was to connect the PC to the telephone and to provide I/O interfaces that were easy to expand and reconfigure. In January 1996, the first version of the USB specification was released, and a subsequent revision (version 1.1) was released in September 1998. The specification allowed 127 devices to be connected together at the same time, with the total communication bandwidth limited to 12 Mbps. Later on, three more members (Hewlett-Packard, Lucent, and Philips) joined the alliance. In April 2000, version 2.0 of the USB specification, which supports transfer rates up to 480 Mbps, was released. Today, USB plays a key role in high-speed (video, imaging, storage) and full-speed (audio, broadband, microphone) data-transfer applications. It also connects a variety of low-speed devices (keyboards, mice, game peripherals, virtual reality peripherals) to the PC.

The USB protocol is strictly hierarchical. In any USB system there is only a single host, and the USB interface to the host computer is referred to as the host controller. There are two standards for host controllers — the Open Host Controller Interface (OHCI, by Compaq) and the Universal Host Controller Interface (UHCI, by Intel). Both standards provide the same capabilities and work with all USB devices; the hardware implementation of a UHCI is simpler, but requires a more complex device driver (and thus puts more load onto the CPU).

The USB physical interconnect is a tiered star topology, with up to seven tiers. A hub is at the center of each star, and the USB host is considered the root hub. Each wired segment is a point-to-point connection between a hub and USB device; the latter can be either another hub that provides additional attachment points to the system, or a device of some sort that provides functional capabilities. The host uses a master/subordinate protocol to communicate with the USB devices. This approach solves the problem of packet collision but also prevents the attached devices from establishing direct communication with each other.

All the data transfers are initiated by the host controller. Data directed from the host to a device is called downstream or out transfer; data directed from a device to the host is called upstream or in transfer. Data transfer occurs between the host and a particular endpoint on the USB device, and the data link between the host and the endpoint is called a pipe. A given USB device may have many endpoints, and the number of data pipes between the host and the device is the same as the number of endpoints on the device. A pipe may be uni-directional or bi-directional, and the data flow in one pipe is independent of the data flow in any other pipes.

Communication on the USB network can use any one of four different data transfer types:

  • Control transfers: These are short data packets for device control and configuration, particularly at attach time.
  • Bulk transfers: These are data packets in relatively large quantities. Devices like scanners or SCSI adapters use this transfer type.
  • Interrupt transfers: These are data packets that are polled periodically. The host controller will automatically post an interrupt at a specified interval.
  • Isochronous transfers: These are data streams in real time with higher requirements for bandwidth than for reliability. Audio and video devices generally use this transfer type.

Like a serial port, each USB port on a computer is assigned a unique identification number (port ID) by the USB controller. When a USB device is attached to a USB port, this unique port ID is assigned to the device and the device descriptor is read by the USB controller The device descriptor includes information that applies globally to the device, as well as information on the configuration of the device. A configuration defines the functionality and I/O behavior of a USB device. A USB device may have one or more configurations, which are described by their corresponding configuration descriptors. Each configuration has one or more interfaces, which can be considered as a physical communication channel; each interface has zero or more endpoints, which can be either data providers or data consumers, or both. Interfaces are described by interface descriptors, and endpoints are described by end-point descriptors. Furthermore, a USB device might also have string descriptors to provide additional information such as vendor name, device name, or serial numbers.

As you can see, a protocol like USB offers challenges to developers who use the Java language, which strives for platform- and hardware-independence. Let’s now take a look at two projects that have tried to bridge the gap.

The jUSB API


The jUSB project was created by Mojo Jojo and David Brownell in June 2000. Its objective was to provide a set of free software Java APIs to access USB devices on Linux platforms. The API is distributed under the Lesser GPL (LGPL), which means that you can use it in proprietary as well as free software projects. The API provides multithreaded access to multiple physical USB devices, and supports both native and remote devices. Devices with multiple interfaces can be accessed by multiple applications (or device drivers) simultaneously, with each application (or device driver) claiming a different interface. The API supports control transfers, bulk transfers, and interrupt transfers; isochronous transfers are not supported because these are used for media data (such as audio and video) that are already well supported by the JMF API (see
Resources) over other standardized device drivers. Currently, the API works on GNU/Linux distributions with either the Linux 2.4 kernel or a back port into 2.2.18 kernel. Thus, most recent distributions are supported; for example, the API works on Red Hat 7.2 and 9.0 without any patches or other upgrades.

The jUSB API includes the following packages:

  • usb.core: This package is the core part of the jUSB API. It allows Java applications to access USB devices from USB hosts.
  • usb.linux: This package contains a Linux implementation of a usb.core.Host object, bootstrapping support, and other classes leveraging Linux USB support. This implementation accesses the USB devices through the virtual USB device file system (usbdevfs).
  • usb.windows: This package has a Windows implementation of a usb.core.Host object, bootstrapping support, and other classes leveraging Windows USB support. This implementation is still in its very early stage.
  • usb.remote: This package is a remote version of the usb.core API. It includes an RMI proxy and a daemon application, which allow Java applications to access USB devices on a remote computer.
  • usb.util: This package provides some useful utilities to download firmware to USB devices, dump the content of the USB system into XML, and convert a USB device with only bulk I/O into a socket.
  • usb.devices: This optional package collects Java code to access a variety of USB devices with the jUSB API, including Kodak digital cameras and Rio 500 MP3 Players. These APIs were specially written to simplify the process of accessing the designated USB devices and cannot be used to access other devices. The APIs were built upon the usb.core APIs, and they will work on any operating system where jUSB is supported.
  • usb.view: This optional package provides a simple USB tree browser based on Swing. It is a very good example program illustrating the use of the jUSB API.

Although the implementation of the usb.core.Host object varies from operating system to operating system, a Java programmer needs to understand only the usb.core package to start developing applications with the jUSB APIs. Table 1 outlines the interfaces and classes from usb.core with which a Java programmer should be familiar:

Table 1. Interfaces and classes in jUSB

Interface Description
Bus Connects a set of USB devices to a Host
Host Represents a USB controller with one or more Buses
Class Description
Configuration Provides access to a USB configuration supported by a device and to the interfaces associated with that configuration
Descriptor Base class for entities with USB typed descriptors
Device Provides access to a USB device
DeviceDescriptor Provides access to a USB device descriptor
EndPoint Provides access to a USB end-point descriptor, structuring device data input or output in a given device configuration
HostFactory Contains bootstrapping methods
Hub Provides access to a USB hub descriptor and some hub operations
Interface Describes sets of endpoints, and is associated with a particular device configuration
PortIdentifier Provides stable string identifiers for USB devices, appropriate for use in operations and troubleshooting

The normal procedure to access a USB device with the jUSB API is as follows:

  1. Bootstrap by getting the USB Host from the HostFactory.
  2. Access the USB Bus from the Host, then access the USB root hub (which is a USB Device) from the Bus.
  3. Obtain the number of USB ports available on the hub, and traverse through all the ports to find the appropriate Device.
  4. Access the USB Device that is attached to a particular port. A Device can be accessed directly from the Host with its PortIdentifier, or can be found by traversing the USB Bus starting from the root hub.
  5. Interact with the Device directly with ControlMessage, or claim an Interface from the current Configuration of the Device and perform I/O with the Endpoint available on the Interface.

Listing 1 illustrates how to obtain the content of a USB system with the jUSB API. The program as written simply looks at the root hub for available USB devices, but it would be easy to improve it to traverse the whole USB tree. The logic here corresponds to steps 1 through 4 above.

Listing 1. Obtaining the content of a USB system with the jUSB API

<code>
import usb.core.*;

public class ListUSB
{
public static void main(String[] args)
{
try
{
// Bootstrap by getting the USB Host from the HostFactory.
Host   host = HostFactory.getHost();

// Obtain a list of the USB buses available on the Host.
Bus[]  bus  = host.getBusses();
int    total_bus = bus.length;

// Traverse through all the USB buses.
for (int i=0; i<total_bus; i++)
{
// Access the root hub on the USB bus and obtain the
// number of USB ports available on the root hub.
Device root = bus[i].getRootHub();
int total_port = root.getNumPorts();

// Traverse through all the USB ports available on the
// root hub. It should be mentioned that the numbering
// starts from 1, not 0.
for (int j=1; j<=total_port; j++)
{
// Obtain the Device connected to the port.
Device device = root.getChild(j);
if (device != null)
{
// USB device available, do something here.
}
}
}
} catch (Exception e)
{
System.out.println(e.getMessage());
}
}
</code>

Listing 2 illustrates how to perform bulk I/O with Interface and EndPoint, assuming that the application has successfully located the Device. This code snippet can also be modified to perform control or interrupt I/O. It corresponds to step 5 above.

Listing 2. Performing bulk I/O with the jUSB API

<code>
if (device != null)
{
// Obtain the current Configuration of the device and the number of
// Interfaces available under the current Configuration.
Configuration config = device.getConfiguration();
int total_interface = config.getNumInterfaces();

// Traverse through the Interfaces
for (int k=0; k<total_interface; k++)
{
// Access the currently Interface and obtain the number of
// endpoints available on the Interface.
Interface itf = config.getInterface(k, 0);
int total_ep  = itf.getNumEndpoints();

// Traverse through all the endpoints.
for (int l=0; l<total_ep; l++)
{
// Access the endpoint, and obtain its I/O type.
Endpoint ep = itf.getEndpoint(l);
String io_type = ep.getType();
boolean input  = ep.isInput();

// If the endpoint is an input endpoint, obtain its
// InputStream and read in data.
if (input)
{
InputStream in;
in = ep.getInputStream();
// Read in data here
in.close();
}
// If the Endpoint is and output Endpoint, obtain its
// OutputStream and write out data.
else
{
OutputStream out;
out = ep.getOutputStream();
// Write out data here.
out.close();
}
}
}
}
</code>

The jUSB project was very active from June 2000 to February 2001. The most recent release of the API, version 0.4.4, was made available on February 14, 2001. Only some minor progress has been reported since that time, probably due to the success of the IBM group in becoming a candidate extended standard of the Java language. However, several third-party applications have been developed based on jUSB, including the JPhoto project (an application using jUSB to connect to digital cameras) and the jSyncManager project (an application using jUSB to synchronize with a Palm OS-based PDA).

The JSR-80 API (javax.usb)

As noted earlier, the JSR-80 project was created by Dan Streetman at IBM in 1999. In 2001, the project was accepted as a candidate extended standard of the Java language through the Java Specification Request (JSR) process. The project is now called JSR-80 and has been officially assigned the Java package javax.usb. The project is licensed under the Common Public License and is developed using the Java Community Process. The objective of this project is to develop a USB interface for the Java platform that will allow full access to the USB system for any Java application or middleware component. The JSR-80 API provides full support for all four transfer types defined by the USB specification. Currently, the Linux implementation of the API works on most recent GNU/Linux distributions with 2.4 kernel support, such as Red Hat 7.2 and 9.0.

The JSR-80 project includes three packages: javax-usb (the javax.usb API), javax-usb-ri (the common part of the OS-independent reference implementation), and javax-usb-ri-linux (the reference implementation for the Linux platform, which connects the common reference implementation to the Linux USB stack). All three parts are required to form a complete functioning java.usb API on the Linux platform. Independent efforts aimed at porting the API to other operating systems (primarily Microsoft Windows) have been reported on the project e-mail list, but no functioning packages have been released yet.

Although the OS-dependent implementation of the JSR-80 APIs varies from operating system to operating system, a Java programmer needs to understand only the javax.usb package to start developing applications. Table 2 lists the interfaces and classes in javax.usb with which a Java programmer should be familiar:

Table 2. Interfaces and classes in the JSR-80 APIs

Interface Description
UsbConfiguration Represents a configuration of a USB device
UsbConfigurationDescriptor Interface for a USB configuration descriptor
UsbDevice Interface for a USB device
UsbDeviceDescriptor Interface for a USB device descriptor
UsbEndpoint Interface for a USB endpoint
UsbEndpointDescriptor Interface for a USB endpoint descriptor
UsbHub Interface for a USB hub
UsbInterface Interface for a USB interface
UsbInterfaceDescriptor Interface for a USB interface descriptor
UsbPipe Interface for a USB pipe
UsbPort Interface for a USB port
UsbServices Interface for a javax.usb implementation
Class Description
UsbHostManager Entry point for javax.usb

The normal procedure for accessing a USB device with the JSR-80 API is as follows:

  1. Bootstrap by getting the appropriate UsbServices from the UsbHostManager.
  2. Access the root hub through the UsbServices. The root hub is considered as a UsbHub in the application.
  3. Obtain a list of the UsbDevices that are connected to the root hub. Traverse through all the lower-level hubs to find the appropriate UsbDevice.
  4. Interact with the UsbDevice directly with a control message (UsbControlIrp), or claim a UsbInterface from the appropriate UsbConfiguration of the UsbDevice and perform I/O with the UsbEndpoint available on the UsbInterface.
  5. If a UsbEndpoint is used to perform I/O, open the UsbPipe associated with it. Both upstream data (from the USB device to the host computer) and downstream data (from the host computer to the USB device) can be submitted either synchronously or asynchronously through the UsbPipe.
  6. Close the UsbPipe and release the appropriate UsbInterface when the application no longer needs access to the UsbDevice.

In Listing 3, we obtain the content of the USB system with the JSR-80 API. The program recursively traverses through all the USB hubs on the USB system and locates all the USB devices connected to the host computer. The code corresponds to steps 1 through 3 above.

Listing 3. Obtaining the content of the USB system with the JSR-80 API

<code>
import javax.usb.*;
import java.util.List;

public class TraverseUSB
{
public static void main(String argv[])
{
try
{
// Access the system USB services, and access to the root
// hub. Then traverse through the root hub.
UsbServices services = UsbHostManager.getUsbServices();
UsbHub rootHub = services.getRootUsbHub();
traverse(rootHub);
} catch (Exception e) {}
}

public static void traverse(UsbDevice device)
{
if (device.isUsbHub())
{
// This is a USB Hub, traverse through the hub.
List attachedDevices =
((UsbHub) device).getAttachedUsbDevices();
for (int i=0; i<attachedDevices.size(); i++)
{
traverse((UsbDevice) attachedDevices.get(i));
}
}
else
{
// This is a USB function, not a hub.
// Do something.
}
}
}
</code>

Listing 4 illustrates how to perform I/O with Interface and EndPoint, assuming that the application has successfully located a Device. This code snippet can also be modified to perform I/O of all four data transfer types. It corresponds to steps 4 through 6 above.

Listing 4. Performing I/O with the JSR-80 API

<code>
public static void testIO(UsbDevice device)
{
try
{
// Access to the active configuration of the USB device, obtain
// all the interfaces available in that configuration.
UsbConfiguration config = device.getActiveUsbConfiguration();
List totalInterfaces = config.getUsbInterfaces();

// Traverse through all the interfaces, and access the endpoints
// available to that interface for I/O.
for (int i=0; i<totalInterfaces.size(); i++)
{
UsbInterface interf = (UsbInterface) totalInterfaces.get(i);
interf.claim();
List totalEndpoints = interf.getUsbEndpoints();
for (int j=0; j<totalEndpoints.size(); j++)
{
// Access the particular endpoint, determine the direction
// of its data flow, and type of data transfer, and open the
// data pipe for I/O.
UsbEndpoint ep = (UsbEndpoint) totalEndpoints.get(i);
int direction = ep.getDirection();
int type = ep.getType();
UsbPipe pipe = ep.getUsbPipe();
pipe.open();
// Perform I/O through the USB pipe here.
pipe.close();
}
interf.release();
}
} catch (Exception e) {}
}
</code>

The JSR-80 project has been very active from its very beginning. Version 0.10.0 of the javax.usb API, RI, and RI for Linux were released in February 2003. It is likely that this version will be submitted to the JSR-80 committee for final approval. It is expected that implementations for other operating systems will soon be available after JSR-80 formally becomes an extended standard of the Java language. The Linux developer community seems to show more interest in the JSR-80 project than the jUSB project, and there have been an increasing number of projects launched using the javax.usb API on the Linux platform.

Conclusion


Both the jUSB API and the JSR-80 API provide Java applications with the capability to access USB devices from a machine running the Linux operating system. The JSR-80 API provides more functionality than the jUSB API, and has the potential of becoming an extended standard of the Java language. Currently, only Linux developers can take advantage of the jUSB and JSR-80 APIs. However, active efforts to port both APIs to other operating systems have been reported. Java developers should be able to access USB devices on other operating systems in the near future. By familiarizing yourself with these APIs now, you can be ready to add USB functionality to your applications when these projects are ready for prime time on multiple platforms.

Resources

其他

本文于2003年9月发表于IBM DeveloperWorks美国网站:

http://www-106.ibm.com/developerworks/java/library/j-usb.html

 

多功能串口设备服务器

By , August 28, 2004 5:12 am

[摘要]

本 文介绍了一个基于Java的多功能串口设备服务器。本服务器能够实现如下功能:(1) 接受从指定串口发送来的信号并将其转发到另外的串口、广播到局域网、或者是通过TCP/IP链接转发给局域网内的其它设备,从而实现局域网内部的信息共 享;(2) 通过TCP/IP链接或者是串口接受其他设备发送给该串口设备的控制信息,从而实现设备的远程控制。

[介绍]

随 着网络技术的高速发展,基于IP技术的局域网已经成为最简单有效的数据交换与共享手段。但是,对于很多遗留设备(譬如说单片机和数据采集设备)来说,唯一 可用的通讯通道就是串口(通常是RS-232)。这些设备一般都配备有专门的数据采集和控制软件,这些软件安装在被称为主控系统的终端或者是PC机上,通 过串口与该设备进行通讯。从串口设备发送来的数据被存储在主控系统的文件系统上,其它设备通过网络访问该主控系统,从而实现数据的共享。对串口设备的配置 和控制,只能够通过主控系统来进行。

这些遗留设备的特征, 就是其“设备–控制终端–网络”体系。在涉及到数据交换与共享的时候,主控系统实质上相当于一个缓冲区。这个缓冲过程使用了效率低下的磁盘操作,从而 使主控系统成为整个数据交换过程中的瓶颈。主控系统的唯一功能是配置和控制该串口设备,用户也只能够通过主控系统来配置和控制该串口设备,这不仅在使用上 给用户带来极大的不便,也带来了硬件资源的浪费。

串口设 备服务器的功能,就是接受串口设备发送来的信息,实时的将其通过串口、网络广播、或者是TCP/IP链接转发给需要这些信息的设备。同时,串口设备服务器 还接受从其它串口或者是网络发送来的信息并将其转发给串口设备。与传统的 “设备–控制终端–网络”体系相比较,串口设备服务器具有如下优势:

(1) 串口设备服务器并不将所交换的数据保留到本地文件系统上,从而消除了 “设备–控制终端–网络”体系中的瓶颈(磁盘操作),从而提高了数据 交换与共享的效率,保证了数据的实时性。

(2) 网络广播技术使得多个设备能够同时利用一个串口设备所提供的数据,从 而提高了设备利用率。

(3) 一台串口设备服务器能够同时为多个设备提供服务。

(4) 远程设备能够通过网络获取串口设备所提供的数据,使得远程数据采集与 处理成为可能。

(5) 远程设备能够通过网络向串口设备发送数据,因此能够从远程对该设备进 行控制和配置。

(6) 用户能够从远程对串口设备服务器进行控制和配置。

由 于以上技术上的优势,串口设备服务器在任何涉及到数据采集与处理的系统中都能够得到广泛的应用。在实验室中采用串口设备服务器,使得科研人员在家里也能够 实时监测实验仪器的运行情况,采集和处理实验数据甚至调整实验条件。在医院里采用串口设备服务器,使得医护人员在办公室里就可以得到各个病人的心电图和脉 搏等数据,这不但提高了医护人员及时发现突发情况的能力,还减轻了医护人员的劳动强度。在航天器上采用串口设备服务器,地面控制人员能够通过无线网络直接 获取传感器数据,修正系统的错误,甚至上载新的任务模块。

本文利用Java实现了一个简单的多功能串口设备服务器。这个服务器能够实现如下功能:

(1) 接受从指定串口发送来的信号并将其转发到另外的串口、广播到局域网、 或者是通过TCP/IP链接转发给局域网内的其它设备。

(2) 通过TCP/IP链接或者是串口接受其他设备发送的控制信息并将其转发给该 串口设备。

(3) 通过TCP/IP链接接受用户的控制指令,从而改变自身的运行参数。

[系统设计]

根据一上所述系统需求,这个简单的串口设备服务器包括如下功能模块:主控模块,远程控制模块,以及数据交换模块。

主控模块的功能是初始化各项运行参数,同时启动远程控制模块。

远程控制模块通过TCP/IP链接接受用户指令并根据指令实现如下功能:改变串口参数,与指定串口设备进行通讯,启动或者终止指定数据交换模块。

数据交换模块接受串口设备的输出数据并转发给其他设备,同时从其它设备接受控制信号并转发给串口设备。根据系统需求我们设计了三个数据交换模块:

(1) 数据广播模块,接受串口设备的输出数据并将其广播到局域网;

(2) TCP/IP数据服务模块,接受串口设备的输出数据并通过TCP/IP链接将其转 发到指定客户机,同时接受该客户机发送的控制指令并将其转发给串口设 备;

(3) 串口数据服务模块,接受串口设备的输出数据并通过另一串口转发给其他 设备,同时接受其他设备发送的控制指令并将其转发给串口设备。

根据以上设计,将各个功能模块命名如下:

主控模块 — DeviceServer
远程控制模块 — RemoteControl
数据广播模块 — Broadcast
TCP/IP数据服务模块 — ServeTcp
串口数据服务模块 — ServeCom

以上所述功能模块,在程序设计中分别作为一个Java类进行实现。功能模块与 Java源代码文件之间的一一对应关系如下:

主控模块 — DeviceServer.java
远程控制模块 — RemoteControl.java
数据广播模块 — Broadcast.java
TCP/IP数据服务模块 — ServeTcp.java
串口数据服务模块 — ServeCom.java

[程序设计]

(1) 主控模块

主 控模块的功能是初始化各项运行参数,同时启动远程控制模块。在这个简单的串口设备服务器中并没有定义任何运行参数,因此主控模块的唯一功能是启动远程控制 模块。本模块从命令行接受一个参数,该参数指定远程控制模块所使用的端口号,远程客户可以通过该端口对本系统进行控制和配置。本功能模块包括如下步骤:

a. 检查用户是否从命令行提供了一个参数。如果是,继续运行下一步;如果 否,输出一条出错信息并退出系统。

b. 检查用户所提供的命令行参数是否可以解释成一个端口号(一个整数)。如 果是,继续运行下一步;如果否,输出一条出错信息并退出系统。

c. 检查用户所提供的端口号是否系统端口(即小于1024)或者是无效端口( 即 大于65535)。如果否,继续运行下一步;如果是,输出一条出错信息并退 出系统。

d. 声明一个远程控制模块,然后启动该模块。

主控模块被保存为DeviceServer.java

(2) 远程控制模块

远程控制模块通过TCP/IP链接接受用户指令并根据指令实现如下功能:改变串口参数,与指定串口设备进行通讯,启动或者终止指定数据交换模块。根据系统需求,本模块又包括如下方法:

系统配置方法:

a. 指定串口设备所在的串口;
b. 指定与该串口设备通讯所使用的参数,包括波特率,数据位,停止位和奇 偶性校验位。
c. 指定其他设备所在的串口;
d. 指定与其他设备通讯所使用的参数,包括波特率,数据位,停止位和奇偶 性校验位。
e. 指定数据广播端口,即客户机用来监听实时数据的端口。
f. 指定数据服务端口,即客户机用来请求实时数据的端口。
g. 指定数据交换模块。为简单起见,本系统一次只能够启动一个数据交换模 块提供数据交换服务。
系统控制方法:

a. 解释控制指令,这个方法解释客户机所发送的控制和配置指令,然后调用 相应的系统控制或配置方法。

b. 启动与串口设备的连接。
c. 切断与串口设备的连接。在切断与串口设备的连接之前必须关闭所使用的 端口或者是切断与客户机的联接。
d. 启动数据交换模块。
e. 终止数据交换模块。在终止数据交换模块之前必须关闭所使用的端口或者 是切断与客户机的联接。
f. 退出系统。在退出系统之前必须关闭所有端口,终止数据交换模块。

由于这个功能模块所需要实现的功能比较多,为节省篇幅起见,以下示例程序中没有设计异常处理功能。在程序的注释行中,对有可能导致异常的地方添加了部分说明。

远程控制模块被保存为RemoteControl.java

(3) 数据广播模块

数 据广播模块的功能是接受串口设备的输出信号,然后将其通过广播将其转发到局域网。在局域网中的所有设备都可以通过监听广播端口来获得串口设备所提供的数 据,从而使得多个设备同时共享一个特殊设备成为可能。这个功能模块首先建立一个广播服务器,然后不断的监听串口设备的输出流。当输出流里面有数据存在的时 候,广播服务器将其取出并广播到局域网。

数据广播模块被保存为Broadcast.java

(4) TCP/IP数据服务模块

TCP/IP 数据服务模块的功能是接受串口设备的输出信号,然后通过TCP/IP连接将其转发给客户机。这个模块还能够接受客户机通过TCP/IP连接发送来的控制信 号并将其转发给串口设备,从而实现了串口设备的远程控制与配置功能。在这个模块中包括三个线程:服务器线程接受客户机的连接请求,数据服务线程监测串口设 备的输出流并将数据转发给客户机,控制信号服务线程监测客户机的输出流并将信号转发给串口设备。为简单起见,这个示例程序一次只能够接受一个客户机的连接 请求,但是用户能够很容易的将其改写成能够同时为多个客户机提供服务。

TCP/IP数据服务模块被保存为ServeTcp.java

(5) 串口数据服务模块

串 口数据服务模块的功能是接受串口设备的输出信号,然后通过串口将数据转发给其它通过串口连接的设备。与TCP/IP数据服务模块类似,这个模块还能够接受 客户设备通过串口发送来的控制信号并将其转发给串口设备,从而实现了串口设备的远程控制与配置功能。通常来说,两个设备通过串口进行通讯要求这两个设备使 用相同的通讯参数,例如波特率,数据位,停止位和奇偶性校验位。但是对于很多遗留设备来说,他们往往只能够使用固定的通讯参数进行工作,从而导致了由于两 个设备由于通讯参数不同而无法共享数据的问题。在这个示例程序中,不同的设备可以使用不同的通讯参数,从而解决了具有不同固定通讯参数的设备之间的数据交 换问题。

在这个功能模块中包括两个线程:数据服务线程监 测串口设备的输出流并将数据转发给客户设备,控制信号服务线程监测客户设备的输出流并将信号转发给串口设备。为简单起见,这个示例程序一次只能够为一个客 户设备提供数据服务,但是用户也能够很容易的将其改写成能够同时为多个客户设备提供服务。

串口数据服务模块被保存为ServeCom.java

[系统测试]

本多功能串口设备服务器的测试应该在局域网中进行。优选的测试方案应该具备如下硬件条件:

计 算机A — 运行本多功能串口设备服务器。本机必须配备Java运行环境和由 Sun公司提供的通讯扩展类库javax.comm,这些软件都可以从Java 软件的主页www.javasoft.com免费下载。再进行测试之前必须根据 该软件包所提供的说明文件正确进行安装,否则在测试的时候系统 将无法找到本机串口。

计算机B — 运行超级终端模拟一个串口设备,通过RS-232电缆与计算机A的串 口COM1相连接。

计算机C — 运行超级终端模拟其它串口设备,通过RS-232电缆与计算机A的串 口COM2相连接。

计算机D — 通过局域网与计算机A相连接,模拟局域网中向多功能串口设备服 务器请求数据的其它网络设备。

在计算机A 上运行本多功能串口设备服务器,然后通过TELNET进入远程控制状态。用户通过命令行方式对服务器进行控制和配置。本服务器所提供的控制和配置指令如下:

SET DEVICE PORT — 设定串口设备所在的串口。本命令接受一个整数 参数,该参数指定串口设备所在的串口。

SET DEVICE PARAM — 设定串口设备所使用的通讯参数。本命令接受一 个参数串,如38400,8,1,0 表示波特率38400 , 数据位8,停止位1,无奇偶检验。

SET PEER PORT — 设定其它设备所在的串口。本命令接受一个整数 参数,该参数指定串口设备所在的串口。

SET PEER PARAM — 设定其它设备所使用的通讯参数。本命令接受一 个参数串,如38400,8,1,0 表示波特率38400 , 数据位8,停止位1,无奇偶检验。

SET BROADCAST PORT — 设定数据广播端口。本命令接受一个整数参数, 该参数指定客户机用来监听数据广播的端口。

SET SERVICE PORT — 设定数据服务端口。本命令接受一个整数参数, 该参数指定服务器用来提供数据服务的端口。

SET SERVICE TYPE — 指定数据服务类型。本命令接受一个整数参数, 1 表示数据广播服务,2 表示TCP/IP数据服务, 3 表示串口数据服务。其它数值都是无效参数。

CONNECT TO DEVICE — 接通串口设备。本命令不接受任何参数。

DISCONNECT FROM DEVICE — 切断串口设备。本命令不接受任何参数。

START SERVICE — 启动数据服务。本命令不接受任何参数。

STOP SERVICE — 终止数据服务。本命令不接受任何参数。

SHUT DOWN — 终止多功能串口设备服务器。本命令不接受任何 参数。

QUIT — 退出远程控制系统。本命令不接受任何参数。

由于远程控制服务器在处理命令之前将命令行转换成大写,因此用户可以用大写或者是小写输入控制与配置指令。

(1) 数据广播功能测试

计 算机A 启动多功能串口设备服务器,计算机B 启动超级终端模拟串口设备。启动多功能串口设备服务器时必须指定一个端口号(如8888)以提供远程控制服务。利用Telnet进入远程控制程序(如 telnet localhost 8888),就可以通过控制指令控制和配置多功能串口设备服务器了。

需 要说明的是,由于Windows 自带的Telnet程序不回显输入数据,因此用户看不到自己所输入的命令。建议用户从一台类似于UNIX的系统远程Telnet到串口设备服务器进行控制 和配置。如果计算机A 的IP为90.0.0.1,多功能串口设备服务器的远程控制服务程序运行在端口8888,那么用户就可以通过telnet 90.0.0.1 8888连接到远程控制服务器。

用户连接到远程控制服务器后,运行如下命令:

SET DEVICE PORT 1
SET DEVICE PARAM 115200,8,1,0
CONNECT TO DEVICE
SET SERVICE TYPE 1
SET BROADCAST PORT 8080
START SERVICE

以 上指令设定串口设备连接在COM1 ,通讯参数为115200,8,1,0。运行在计算机B 上的超级终端应该使用同样的通讯参数。成功的与串口设备建立起连接后指定8080为数据广播端口,再指定系统提供数据广播服务,最后启动数据广播服务。这 时候,在同一局域网内的其它计算机(如计算机D )就应该能够在8080端口监听到由串口设备(计算机B )所发送的数据。

本文提供了一个示例程序可以用来监听广播到指定端口的数据。该程序从命令行接受一个参数,这个参数指定监听的端口。这个程序被保存为 BClient.java

在 机器D 上运行以上程序并指定8080为监听端口。在机器B 的超级终端窗口内随意输入作为串口设备的输出数据,这些数据被多功能串口设备服务器所接收并实时的广播到局域网,因此机器D 的屏幕上应该同时打印出这些数据来。如果局域网网中同时还有其它计算机运行以上接收程序并指定8080为监听端口,那么这些计算机也能够同时接收到串口设 备的输出数据。

(2) TCP/IP数据服务功能测试

在远程控制终端输入如下控制指令测试TCP/IP数据服务功能:

STOP SERVICE
SET SERVICE TYPE 2
SET SERVICE PORT 8023
START SERVICE

以 上控制指令指定多功能串口设备服务器在端口8023启动TCP/IP数据服务。从机器D 通过Telnet连接到该端口(如telnet 90.0.0.1 8023)就可以接收到串口设备所输出的数据。在机器D 上所输入的数据,也被实时的传送到串口设备,因此在机器B 的超级终端窗口内能够看到从机器D 所输入的数据。因此,局域网内的设备不但能够通过串口设备服务器利用该串口设备进行远程数据采集与处理,还能够实现串口设备的远程控制和配置。

(3) 串口数据服务功能测试

在远程控制终端输入如下控制指令测试串口数据服务功能:

STOP SERVICE
SET PEER PORT 2
SET PEER PARAM 38400,8,1,0
SET SERVICE TYPE 3
START SERVICE

以上控制指令指定其它串口设备被连接在COM2上,所使用的通讯参数为38400, 8,1,0。 最后面两个控制指令指定系统运行串口数据服务。

计 算机C 上运行超级终端程序,其通讯参数为38400,8,1,0。这时候串口设备(计算机B )可以接收到其它设备(计算机C )所发送的数据,其它设备(计算机C ) 也可以接收串口设备(计算机B )所发送的数据。我们注意到,两个串口设备( 计算机B 和C ) 所使用的通讯参数是不同的,但是他们可以通过这个多功能串口设备服务器进行数据交换。

(4) 其它功能测试

在远程控制终端输入如下控制指令:

DISCONNECT FROM DEVICE

以上控制指令切断与串口设备的连接。如果当前正在提供远程数据服务( 如数据广播服务,TCP/IP数据服务,串口数据服务),这项服务将被关闭。

QUIT

以上控制指令终止客户机与远程控制终端的会话,多功能串口设备服务器的所有配置保持终止会话前的状态,正在提供的远程数据服务继续提供。

SHUT DOWN

以上控制指令强制停止多功能串口设备服务器的执行。当前正在提供的远程数据服务将被关闭,与串口设备的连接将被切断。

(5) 测试结果

作者对本系统的功能进行了全面的测试,实际测试环境如下:

计算机A — Windows 2000英文版 + Java SDK 1.3 + Java Comm API
计算机B — Windows 98英文版 + 超级终端
计算机C — Windows 98英文版 + 超级终端
计算机D — Windows 98英文版 + Java SDK 1.3
计算机E — Red Hat 6.1

所 有机器通过100M高速Ehternet连接。计算机B 通过RS-232电缆连接到计算机 A 的COM1,计算机C 通过RS-232电缆连接到计算机A 的COM2。在实际测试中,通过计算机E 远程连接到计算机A 进行远程控制与配置。测试结果表明,该系统能够实现远程控制与配置与远程数据服务等全部功能。

[结论]

本文设计和实现了一个基于Java的多功能串口设备服务器。本多功能串口设备服务器能够实现如下功能:

(1) 远程控制与配置。

(2) 为串口设备提供远程数据服务。数据广播服务使得局域网内的多个设备能 够同时利用一个串口设备所提供的数据;TCP/IP数据服务使得局域网内的 设备能够通过TCP/IP连接获得串口设备所提供的数据,并且能够远程对该 串口设备进行控制和配置;串口数据服务使得两个使用不同通讯参数的串 口设备能够进行数据交换。

(3) 本系统不但实现了在局域网内的串口设备信息共享,并且大幅度提高了数 据交换的速度和效率。

(4) 本系统在Windows 平台上测试成功。由于Java语言的垮平台特性,本系统 只需要进行很小的改动就可以移植到其它平台上。

(5) 本系统在涉及到数据采集与处理的行业中具有广泛的应用前景。

[其他]

本文于2001年8月首次发表于IBM DeveloperWorks中国网站。
http://www.ibm.com/developerWorks/cn

基于PPP协议的Linux与Windows CE网络

By , August 23, 2004 11:21 pm

本文介绍了通过网络实现 Linux 主机与 Windows CE 设备协同工作的方法。本文首先利用 PPP 协议在 Linux 主机与 Windows CE 设备之间建立起连接,然后在 Windows CE 设备上运行一个 FTP 服务器使得 Linux 主机能够访问 Windows CE 设备上的资源。本文所介绍的解决方案,对 Windows 9x/2000/NT 主机同样适用。

背景介绍

Linux 是一个类似于UNIX 的操作系统,它起源于芬兰一个名为Linus Torvalds 的业余爱好,但是现在已经是最为流行的一款免费操作系统。普通用户在Linux 上办公、浏览网站、发送邮件以及玩游戏,许多大学和科研机构也Linux 来完成日常 的计算任务。在商业领域,由于Linux 系统价格低、安全性能高并且非常稳定,许 多公司均将自己的服务器构建在Linux的基础上。根据国际商用数据公司(IDC)的统计,世界上大约有三分之一的网站服务器使用Linux作为操作系 统。

Windows CE,根据微软公司在Windows CE and Pocket PC: FAQ 中的定义,是操作系统开发商用以构建专有操作系统的一系列组件。原始设备制造商(OEM) 可以 向微软公司购买一个称为”Windows CE平台开发系统”的集成开发环境并利用该系 统组装和编译基于Windows CE的操作系统,该操作系统包括一系列基于Windows CE 的组件以及开发商自行开发的应用软件或者是设备驱动程序。由于基于Windows CE 的操作系统具有与微软Windows 系列操作系统相类似的用户界面,因此受到众多最 终用户以及开发商的青睐。目前Windows CE已经被广泛应用在手机,掌上型电脑,个人数字助理,快译通以及电子字典等便携式设备上。

长 期以来,Windows CE设备的用户还需要配备一台基于Windows 9x/2000/NT的 主机用于与Windows CE设备交换数据。在该主机上运行微软公司提供的Windows CE 服务软件,该软件通过一条RS-232数据线与Windows CE设备建立起点对点连接,用 户可以通过这个服务软件访问Windows CE设备,但是局域网里面的其它计算机不能 够访问该Windows CE设备。如果需要使得局域网里面的其它计算机也能够访问该设备,则需要为该设备安装昂贵的专用网卡以及相关接入设备,是一种非常不经济的 解决方案。

本 文利用Red Hat Linux 7.2操作系统自带的PPP服务器与Windows CE设备之间 建立起TCP/IP连接,然后在Windows CE设备上运行一个FTP服务器使得Linux主机能 够访问Windows CE设备上的资源。由于本方法基于Windows CE设备自带的RS-232数据线,不需要购买额外的任何设备,因此是一种经济实用的解决方案。此外,本文 所介绍的解决方案,对Windows 9x/2000/NT主机同样适用。

连接Linux与Windows CE

点 对点数据传输协议(Point to Point Protocol, PPP)是一个通过串口线传送 IP数据包的协议。使用PPP 协议,一台计算机能够通过串口线、电话线等通讯设备登陆到远程主机并且利用该主机或者是主机所在网络的资源。在点对点通讯中包括服务器和客户机两个部分, 其中客户机向服务器请求网络连接,服务器接收客户机的请求建立网络连接并分配给客户机相应的网络资源。当网络连接建立起来以后,服务器和客户机之间是严格 对等的。由于Linux操作系统通常都带有PPP服务器和客 户端程序,而Windows CE操作系统通常仅带有PPP客户端程序,因此我们使用Linux 主机作为PPP服务器,Windows CE设备作为PPP客户端。

为了使用Linux主机作为PPP服务器,我们首先必须确认该主机上是否已经安装有PPP服务器程序pppd。通常该程序被安装在/usr/sbin目录下,我们可以利用下面 的命令查找该目录下是否存在这个文件:

ls /usr/sbin/pppd

最 近正式发行的Linux操作系统(例如Red Hat Linux 6.x/7.x)通常都已经预先 安装有PPP服务器程序。如果Linux 主机尚未安装PPP服务器,那么我们应该首先下 载并安装一个PPP服务器程序,例如pppd2.3.4。安装该程序包可能还需要其它包的支持,由于应用程序的安装已经超出了本文的讨论范围,请感兴趣的 读者自行参考 其它相关资料。

确认PPP服务器已经安装在Linux主机上之后,我们需要对Linux 主机进行一些必要的配置,为了进行这些配置我们需要拥有root权限。

建立文件/etc/ppp/peers/wince,内容如下:

<code>       /dev/ttyS0 115200 crtscts
connect '/usr/sbin/chat -v -f /etc/ppp/wince.chat'
noauth
local
90.0.0.1:90.0.0.2
</code>

建立文件/etc/ppp/wince.chat,内容如下:

<code>       TIMEOUT 3600
"CLIENT" "CLIENT\c"
"" "SERVER\c"
</code>

在上面的两个配置文件中,使用wince 作为文件名仅仅是用来表示这个配置文 件是给一个Windows CE设备使用的。读者也可以自行选用其它的文件名,例如palm 或者是handheld等等,但是必须保证两个文件名是一致的。

配 置文件/etc/ppp/peers/wince指定使用串口ttyS0以115,200 bps的速率与客户设备建立连接,noauth参数说明在客户机请求连接的时候不需要身份认证。在这 个对等连接中,服务器(Linux 主机)的IP是90.0.0.1,客户机(Windows Ce设备)的 IP是90.0.0.2。配置文件/etc/ppp/wince.chat中的TIMEOUT参数指定服务器的等待时间,如果超过这个时间仍然没有接收到 客户机的连接请求则终止当前的服务器程序。如果有读者需要更进一步的了解相关的配置,请自行参考chat以及pppd的相关 文档。

在Windows CE设备端需要做的配置相对来说比较简单。由于Windows CE默认的自动连接功能占用了该设备的串口,我们首先需要停止使用该功能。在开始菜单中选择”设置->通讯->PC连线”并将其设置为不启用 与PC的连接即可停止该功能。然后我们重新建立一个连接,在开始菜单种选择”程序->通讯->连接管理器”,然后点击 “新建连接”图标,将新的连接命名为Linux 并指定连接类型为”直线连接”,在下一 步中指定使用COM1进行连接并设置其通讯速率为115,200,在TCP/IP 设置中指定该设备的IP为90.0.0.2。点击OK存盘以后该连接会出现在”程序->通讯”菜单里面。

利用如下命令在Linux主机上启动PPP服务器:

pppd call wince

在Windows CE 设备上启动新建的连接(程序->通讯->Linux)之后,网络连线图 标会出现在Windows CE设备的任务栏上,Linux 主机则显示如下信息表明已经成功 与Windows CE设备建立起连接:

<code>       Serial connection established.
Using interface ppp0
Connect: ppp0 <--> ttyS0
found interface eth0 for proxy arp
local  IP address 90.0.0.1
remote IP address 90.0.0.2
</code>

我们还可以使用Linux 主机提供的ping命令来验证是否已经成功与Windows CE 设备建立连接:

ping 90.0.0.2

如果Linux 主机已经成功的与Windows CE设备建立连接,那么我们应该能够看 到类似于下面的信息:

<code>       PING 90.0.0.2 (90.0.0.2) from 90.0.0.1 : 56(84) bytes of data.
64 bytes from 90.0.0.2: icmp_seq=0 ttl=32 time=26.587 msec
64 bytes from 90.0.0.2: icmp_seq=1 ttl=32 time=19.928 msec
64 bytes from 90.0.0.2: icmp_seq=2 ttl=32 time=19.939 msec
64 bytes from 90.0.0.2: icmp_seq=3 ttl=32 time=19.947 msec
</code>

基于Windows CE的FTP软件

当 我们成功的在Linux主机与Windows CE设备之间建立起PPP连接之后,下一步应该做些什么呢?当然,我们需要一些合适的程序用来在Linux 主机与Windows CE 设备之间进行文件交换。我们现在已经能够利用TCP/IP协议在Linux主机和Windows CE设备之间传输数据,很显然FTP程序是一个合适的选择。

FTP(File Transport Protocol,文件传输协议)是一种被广泛使用的在网络上进行文件交换的协议。由于数据传输可靠性的要求,FTP 是一种基于TCP/IP的传输 协议。在一个FTP 会话中包括一个服务器端和一个客户端,客户端主动连接到服务器端并向服务器发送文件传输请求,服务器端等待客户端的接入并处理客户端的文 件传输请求。

PE FTP Explorer是非常流行的基于Windows CE的FTP客户端软件,同时也是一 个功能齐全的文件浏览器。与在PC机上常用的Cute FTP和WS FTP等FTP 客户端相类 似,用户能够利用鼠标(指针)放缩本地端和服务器端的目录树,上载或者是下载文件和目录,也可以对文件或者是目录进行改名和删除。这个软件可以从CE Archive 网站(http://www.cearchives.com/ftp.html)获得。在该网站读者还可以找到另外 一个很流行的FTP客户端vxFTP。

FTP 客户端软件的功能虽然已经非常的完备而且操作简单,但是仍然不可避免的要收到便携式设备窄小的显示器的限制。如果能够在便携式设备上建立一个FTP 服务器,那么文件传输操作就可以在Linux主机上利用常用FTP客户端的进行。

ftpsrv.exe 就是这样一个基于Windows CE的FTP服务器软件。这个仅有28.5 KB 的小程序,除了不提供身份认证功能和Passive 传输模式以外,能够处理大多数常 见的FTP 请求。利用微软提供的Windows CE服务软件将ftpsrv.exe上载到便携式设备的任意目录下,启动该程序以后在任务条上会出现一个类似于一台计算机连接两个便携式设备的小图标。利 用指针点击该图标以后会出现一个小小的控制窗口,在这里我们可以改变FTP服务器的端口号或者是终止该程序。

ftpsrv.exe可以从http://pda.tucows.com/或者是http://www.oohito.com/获 得。在这两个网站读者还可以找到更多有用的小程序。

其它

如果有读者使用的是Windows 9x/2000/NT主机,那么也可以利用Windows 提供 的直线电缆连接功能与Windows CE设备建立起PPP连接。

例 如:在Windows 2000主机上,从开始菜单中选择设置->网络和拨号连接->新建连接。在随后出现的网络连接向导中选择直接连接到另一台计算机并将该机器配 置为主机。选择合适的通讯端口并配置通讯速率以后,该主机作为PPP 服务器等待 客户机接入。同样,在Windows CE设备上新建一个连接,指定合适的通讯端口并配 置起通讯参数以后,即可与Windows主机建立起点对点连接。由于Windows主机已经配备了动态网络地址分配(DHCP)服务器,因此 Windows CE设备既可以使用实现指定的静态IP地址,也可以使用服务器实时分配的动态IP地址。但是,由于直线电缆连 接所允许的最高传输速率为19,200 bps,使用Windows 9x/2000/NT主机作为PPP 服 务器似乎比不上Linux主机实用。

如 果将PPP 服务器设置为网关,则局域网里面所有的机器都可以通过改网关访 问已经连接到网络上的Windows CE设备。在Linux 主机上,可以通过ipchains将该 主机设置成透明网关;在Windows 9x/2000/NT 主机上,可以通过Win Proxy等代理服务器软件将其设置为透明网关。如果有读者需要更进一步了解如何将Linux 或者是Windows主机设置为透明网关的方法,请自行阅读其它参考资料。

本文于2002年2月首先发表于IBM Developworks中国网站。

http://www-900.ibm.com/developerWorks/cn/linux/l-tip-prompt/tip16/index.shtml

Panorama Theme by Themocracy