Create ubiquitous controlled access to devices using UPI Developing consistent, reliable Web applications that interface to different devices — such as home networks, home automation systems, or realtime telemetry devices — can be vastly simplified by treating devices as URLs. The URL programming interface (UPI) effectively provides a set of URLs for a device that are available to any user capable of performing the HTTP protocol. HTTP has become so universal that, in college computer courses, students are often given as an assignment the creation of an HTTP stack. This trend is due to the growing interest in connecting devices to the Internet. Sun Microsystems Laboratories has used the Java language to develop a technology that allows users to deploy very small HTTP stacks, with a core of less than 100 KB. These small servers can be embedded in devices or used as application servers that are similar to traditional Web servers. Such minimal servers can be used to provide an integrated presentation and service layer for a device. Since it can be a Web server that answers to URL requests, universal access to devices from any Internet node is achieved.Several prototypes have been built for smart cards, realtime weather stations, and home automation. This article demonstrates how HTTP stacks can be used to deploy interfaces to devices, creating an extranet that contains those devices. The technology discussed in this article was developed at Sun Labs, which has built several prototypes that provide authenticated access to any device on the Internet capable of supporting Java directly or via a proxy.The UPI was developed by Sun Labs in response to customer desires to deploy Java Card smart cards to large user populations on disparate targets. While developing a solution for such large scale deployment of smart cards, it was found that the same technology could be used for interfacing a multitude of devices, such as weather stations, home automation systems, devices in factories, and equipment in stores. One of the most useful benefits of this architecture is that the different components can easily be used with each other. For example, you can easily use a smart card to authenticate access to your home by having it interact with your home network and/or environmental systems. Supporting devices in Web applications will add new utility to the Internet, if the technology is implemented securely. Java technology is perfect for this type of application due to its small size and security model. How do you access a device remotely using your Web borrower in a secure manner, without allowing other users to do the same unless they are also authorized? As Internet aware devices (IADs) become widespread, protecting the data they contain becomes crucial. To date, many security systems on the Internet are immature, with the use of passwords and PINs nominally required but easily circumvented. In this article, we will describe how the UPI security services provide an easy way to build an authentication access solution that does not rely on this inadequate password-based security.While some devices have already become widely available on the Internet, the approach described here is more of a style than an API. Lets start with some specific situations in which this technology would be appropriate.Home networkEarlier we mentioned the growing number of users that have digital bits spread out over two locations, the office and the home. The home network provides access to shared peripherals, computers, and other devices, like entertainment and environmental systems. Remote access to this network is valuable to users that are away from their homes just as it is to those that are away from their offices. Many homes have important corporate data in them in addition to personal data, and we should not rely on traditional access architectures for the sort of security features required. The UPI architecture can be used to build a controlled access environment that provides tailored custom services presented on Web pages; this is an alternative to teaching all potential users of such a system how to use FTP and telnet, and then ensuring that secure versions of these services are available everywhere. UPI makes possible a more pragmatic approach — putting up services on Web pages and providing these services only after users have given the appropriate cryptographic credentials. Home automationHome automation has been identified as a growth area by many companies, which are currently developing products that let consumers better utilize the equipment in their homes. As the home network becomes common and is used for creating and storing important files, users will need to access it from the office or other remote locations. The UPI architecture provides an easy framework for building secure remote access from a Web browser and easily supports authentication, which is crucial when making your home systems accessible via the Internet. In this article we will discuss the application of the Web paradigm to the home automation market, an arena currently composed of hundreds of products with proprietary interfaces, all of which are totally insecure and not Web-enabled. What if we could bring order to this mish-mash so that every device in your home had a URL with some amount of functionality behind it? Better yet, what if you could script applications using HTML that allowed you to do important things, like shut down lights, without running around to every room?Process controlThe process control industry, which, broadly speaking, focuses on the construction of plants that in turn make things like cereal, cars, paper, and so on, can save millions of dollars by replacing its custom protocols with Web-enabled devices. Virtually every plant in the world has its own set of unique protocols for communicating with devices, which adds to cost and complexity. Dallas Semiconductor has developed a product that implements a small TCP/IP stack with Web application support on a very small, low-cost board (see Resources for more information). Some of this technology will be presented in greater detail this coming November at IEEECON. If I were designing a new factory, I would use a Web-based architecture that requires that all devices communicate via Jini or HTTP protocols on the main interconnection network, and support all of the legacy devices with proxy services that convert the specific device protocols into a URL protocol. The only architecture that fits this description is UPI. For example, to read conveyor belt status you might see something like this:http://papercompany.plant5.building6.flr3.conveyor1/Status.html Once you’ve read the status, you could use the following URL to change a conveyor belt’s realtime routing: http://papercompany.plant5.building6.flr3.conveyor1/Route?close=down&ope Building such a system with Java will produce a software system that is more secure and easier to maintain than current approaches. If you instead chose to use typical current technologies, you would encounter a host of difficulties, including:Custom protocolsLanguages that have potential security flaws, such as direct access to the stack, private members using pointers, or no type safetyOut-of-band facility for updating codeNo direct platform support for the Web and URLThe above problems have arisen in my real-life experiences developing just the sort of system under consideration. My goal was to allow remote corporate locations to participate more in the day-to-day operation of a plant. I spent several years creating applications for the pulp and paper industry, and in this particular project we developed a packet-switched network that cost several million dollars. It let users view the status of the paper winders and calendaring machines in plants distributed throughout the world. Winders roll up the paper, and calendars make the paper surface glossy. Today, I could base a solution to this problem on UPI and a low-cost, off-the-shelf, single-board computer that runs Java or Embedded Java; forty such boards would have been all that was necessary, and this would cost less than 0,000 — significantly less than the old multimillion dollar solution. We will discuss this in more detail later.One of the challenges and areas requiring further interface is the lack of state on the Web. For example, it is not acceptable to have to reload a Web page in order to get accurate up-to-date data on it. Java solves this problem quite easily by allowing Web applications to have state. Remote corporate locationsCorporations possess widely distributed enterprises and could benefit from being able to offer services — energy control, maintenance, and alarm services, for example — to remote locations. Integrating these services will reduce costs significantly. In 1979, while working for GTE, I installed the first networked electronic cash registers for McDonald’s. These registers would call up corporate headquarters and report on daily transactions, and this information was used to schedule the shipping of product. Today, you can easily install a network in a store and query the store’s various devices, including fryers, filters, thermostats, alarm and fire control systems, and so on. Corporations can reduce costs by centralizing administration. As with home automation, security is extremely important to remote corporate applications. If you have a thousand stores on the Internet, how do you control access easily?UPI Interface to devicesSun Labs has developed three prototypes that demonstrate how the UPI can be used to support the following specific devices. With a little imagination, this implementation can be abstracted to conveyor belts, sensors, and so on.Smart card/Java Card technology: Java Card technology provides the cornerstone for building secure Web-enabled applications that can provide security while relying on a little more than a password. Java Card also provides a secure storage location for confidential profiling data. See the Resources section for a list of articles on Java Card technology.The X10 home automation device: X10 is an ancient protocol for controlling devices over the Web using the power line network. There have been many new efforts in the area of home automation; however the most widely deployed technology is still the venerable X10. You can buy various devices that support the X10 protocol, which are then controllable from a computer or controller. Some X10 devices include modules that turn lights and appliances on and off. Sun Labs has used the UPI to put an X10-enabled house on the Internet with secure access using Java Card.Weather stations: A weather station is primarily a read-only device, in that you read the temperature, wind speed and direction, barometric pressure, rainfall, and so on. There are some parameters you might want to set, like calibration of the weather vane or altitude above sea level. Think of this device as representing a broad range of devices that provide information.The solutionThis article will demonstrate how, from anywhere on the Internet, you can access your home, office, and/or factory — or give others the privilege of accessing the same — through an authentication process. Once you are authenticated, you are presented with a Web interface to the device. Many products out there in the Windows world do this kind of thing, but they do it using different languages and interfaces, resulting in expensive, complicated products and a security architecture that can be hard to understand. This article describes a solution in which the UPI is used to provide authentication, device control, and realtime telemetry. Let’s look at how the UPI solves the problem of interfacing to Java Card-compliant smart cards first, since these cards will be the cornerstone of our authentication system. As time goes on, security schemes that only require a PIN will probably lose out to architectures that implement security schemes based on both something you physically posses — a Java Card — and something you know — a PIN. Please note that in discussing the UPI for Java Card technology, we will discuss some aspects that go far beyond our needs for the remote access requirements mentioned above. The Java Card UPI interface on its own will get a future article providing more detail on how the UPI can be used to deploy Java Card applications with several million users.Architecture overviewThe home, factory, store, or other location must protect itself (in a strange way) from malicious and unauthorized users. This section will look at our three domain-specific examples: applications requiring authentication, control of X10 devices, and access to a weather station. As mentioned earlier, authentication and controlled access is key to this type of architecture. The UPI technology does this by providing an HTTP stack that decodes all URLs from a client and determines if the client is authorized to access this URL. Once the user supplies the proper cryptographic credentials, he or she is granted access. At that point, the user can issue commands to the specific device via the proxy. Examples of the sorts of commands sent follow:Get the current temperature in the house: Allows you to decide whether to turn on the air conditioner so that the house is cool by the time you get home. While some of the current applications for the home are not that interesting, homes will become increasingly more automated and automation products will be available via Web sites in the not too distant future.Turn on the camera and the light: Lets you see if the weather station that you mounted on the side of your house is operating correctly. If the station is collecting values for wind speed and wind direction that seem to be incorrect, you can debug this problem remotely by asking for wind speed samples and seeing what the relative movements on the weather station sensors are. Of course, this needs a cheap cellular modem chip that you can just throw onto a board such as the new TINI board from Dallas Semiconductor. I would consider 00 a good price for such a device.Let’s look at what exactly is on this device:TINI boardCellular modem interface and antennaJava iButton chip for authentication accessWeb server and software for appearing as node on the Internet when calledRS232 parallel interfaces for connecting to various devicesPower line interfaceBatteryGive me file MEMO.HTML: Sends you the file you forgot to grab from home this morning. Consider the freedom from worry if your home network is always online.Up to now we have been discussing the applications and the requirements. Now it’s time to consider the technology that will help us realize these applications. The UPI architecture is very easy to understand and deploy, and it doesn’t rely on any new protocols in the short term; it easily supports new concepts like Jini as market acceptance continues. The UPI architecture at its core consists of a series of handlers that are similar to servlets but have fewer features. These handlers are mapped to incoming URL requests. This allows the UPI to be put on very small devices like the TINI board. The UPI supplies a number of handlers, for things like file service, CGI scripts, and so on. Application developers can develop handlers for devices by simply coding a few required methods like init and respond, along with code that understands the device grammar you require.In the following three sections we examine UPI access to the three devices we mentioned earlier: a Java Card-compliant smart card, a weather station, and a power line interface via X10.UPI interface to Java Card-compliant smart cardsThe request: http://www.digiorgio.com/SecureTokenServices/VerifyPersonalCode?pin=123456 78?challenge=76458924659264 asks that a handler called SecureTokenServices process the command VerifyPersonalCode with the arguments supplied. The arguments are a PIN and a challenge. The challenge is a random collection of bits generated for purposes of implementing a challenge-response protocol. The handler takes the arguments and, in this case, generates a cryptographic signature, which it returns as a URL-encoded name value pair. The cryptographic signature was generated by sending the string to a Java Card using an Open Card service (see Resources for more information on Open Card). The cryptographic signature can then be sent to the server, which can determine the validity of the signature.Using smart cards on various systems is still subject to errors and is expensive to deploy due to version issues and competing browser security models. Sun Labs has solved this problem by creating an architecture that utilizes the latest versions of Java and Java Card and that is independent of Microsoft and Netscape. The architecture also supports non-Java smart cards. An excellent write-up of an interface to a non-Java card can be found in Resources below. This architecture is built on the concept of UPIs that create small Web servers, which in turn get wrapped around physical or logical devices and the reverse proxy technology developed at Sun Labs and used in Sun.net.As we mentioned earlier, the vast number of current smart card solutions on the market combines with the plethora of methods for accessing the Internet to pose a challenge for MIS and IT departments. The problem is even more acute in the consumer world. The UPI architecture solves this problem by making the client browser independent; an additional piece of technology for the server, to be discussed in later articles, has the potential to make Web servers appear to be equal in terms of authenticated access and services. The current concept of the browser owning both the card and the API interface to the card decreases the utility of a card that only works with browser from company A or B. As much as I would like to see a browser-only world, there are still many applications that need to have access to smart cards independent of the browser. It would be better to have the resource — a smart card, in this case — appear as a shared resource that is available to all applications on the network, both local and remote. The core concept of UPI involves speaking to a smart card and reader combined as a HTTP stack; in other words, the reader and card look like a bunch of URLs that provide responses to queries. Normally, Web pages are disk files or data generated from programs. In this case, the data returned to you comes via proxies from a smart card reader that contains a card. The client software is called PersonalCard Services, and the server side products are called PersonalCard Service providers. Service providers provide server implementations of code that complete client requests and/or transactions that require server services.Four large groupings of these services follow. The PersonalCard Server has working prototypes of the Web application support abilities described below.Authenticated Web access: Each URL can be assigned an access control list. This control list can specify the valid authentication algorithms and process.Personal Profiling: Without forms many Web applications would not be possible. Forms are an essential user interface component, yet very little has been done to make the process of filling one out automatic and secure. By using smart cards and the techniques described in this article, you can gain control of your personal data instead of trusting various machines and companies to keep it up to date for you. We sometimes refer to this personal data as personal profile data.Transaction systems for micro- or macropayments: Some transaction architectures are too heavyweight for the Web when the monetary amounts are small. The smart card UPI allows everyone to transfer money from one user on the Internet to another. This could be as popular a service as instant wire transfer.Virtual ATM: Why go to an ATM when you can download money directly to your smart card?The PersonalCard Server is a minimal HTTP 1.1 server that understands URLs of the form: http://somehost:someport/SecureTokenServices/GetId This type of programming is an example of UPI URL that queries a handler for the operation of the GetID method. The last element in this path is not treated as a file or as a CGI script, but rather as an identifier that allows the handler SecoreTokenServices to dispatch appropriate processing. In this case, the UPI has been applied to a specific problem and can be called something like SmartCardUPI. The GetID path component returns the ID of the smart card in the reader. This approach lets non-Java programmers easily develop smart card applications using JavaScript. We have also applied this approach to other devices to control X10 power line networks, weather stations, and the implementations are called X10UPI and WeatherStationUPI, on which more below. The Sun Labs approach minimizes IT deployment costs because it allows readers and cards to be treated as addressable Web servers. These servers can be maintained over the Web using simple HTML and JavaScript macros, or using Java programs and applications.UPI interface to weather stationsThe current version of the weather station interfaces to a computer that has a Java application; this computer in turn manages the communication. We discussed this in prior articles in great detail (see Resources). The UPI allows us to build on this previous work and make low-cost, easy-to-deploy interfaces for these sorts of devices. A typical URL to get a sample would be something like this:http://www.digiorgio.com/Weather/GetSample The link above is real; go ahead and try it. How does it work? The weather handler is queried for a current reading. It then decodes the request and communicates with the Dallas 1-Wire weather station to get an XML sample. (See Resources for more information on this product.) It should be obvious that this process can be generalized to any device with which you can communicate from a local computer. UPI interface to X10 power line controllersX10 is a widely distributed protocol for controlling devices in the home. Each device is assigned a unique ID and understands a small vocabulary — a light switch would only need to understand On, Off, and Dim commands, for instance. These units can be controlled over the power line by using an interface that typically connects to the serial port on your controller. In 1998 Sun Labs and Dallas Semiconductor developed Java-based controllers that are small enough to fit into a light switch. One of Java’s strengths is its ability to take dated legacy architectures and support quick upgrading of the system to a Web-based interface that can be easier to use and deploy. The X10 UPI interface provides a URL-based interface to X10 so you can issue a command, from your browser.For example:http://yourhome:1000/X10/HC=10&UC=11&FC=ON asks for a device with a house code of 10 and a unit code of 11 to be turned on. (For more information on the X10 protocol look in the Resources.) An appealing JavaScript, Java, or HTML interface can easily be put on top of the core functionally to create Web-enabled interfaces. Most of the products from the X10 companies are Windows-based and are pretty useless from an Internet perspective because you have to log into machines all day to get information. The X10Handler.java code in Resources implements the handler required to process X10 commands with the TW523 module and the two-way controller. Let’s move on to another application, this one targeting the devices in your home. How would you specify control of the temperature? You would need a thermostat that interfaces with your furnace and is accessible to your control device; typically, this device is your computer. The URL might look like this:http://www.digiorgio.com/X10/SetTemperature?Zone=Upstairs?Temp=62 The home automation handler is being asked to change the heating, ventilation, and air conditioning settings. Dampers in your home can be controlled remotely so that heating is directed to rooms where it is needed.The HTTP stack finds the correct handler and supplies the parameters from the requester. The handler communicates with the home automation controller du jour and provides information back to the user. You can see that, in order to get to the home automation system or the weather station, you need to first get through the authentication process. One of the key concepts is that gaining access to files or devices is no different from gaining access to a URL. Incidentally, Sun Labs has written more than 10 different handlers for serving files out of EPROM, for form-filling using XML and Java Card, and for many other useful purposes. For more information, see the e-mail link in Resources. UPI and JiniOne may question the utility of the UPI given the arrival of Jini. As Jini technology develops, the use of HTTP stacks for solutions to problems like these will decrease, as it should. The weather station UPI has been enhanced to support a Jini interface as well as a UPI interface. Similarly, the other handlers can be augmented to support Jini interfaces so that Jini clients can perform actions on devices. The UPI architecture complements Jini technology by allowing the deployment of intranet applications that use Jini exclusively, yet allows the same code base to present a URL interface for Internet users. This code will be posted to the Jini Web site in next few weeks. (See Resources for the URL.)X10Handler for a TW523 maps requests to actions on the power lineThe following two files demonstrate how to write a simple handler for the UPI that allows users to send X10 commands to power line devices. The first file is an abstract class that provides some of the common implementations and defers implementation of device specific methods to other classes, in this case the TwoWayHandler.java. The TwoWayhandler communicates with a device that connects to the RS232 port and connects on this port to signal levels appropriate for a TW523. For more information on the X10 devices, look at the URLs in the comment sections within the code.GenericX10Handler<i>/** * Generic Support for simple X10 devices. * X10 is a simple powerline control protocol. This handler maps * URLs into X10 commands, allowing home automation control * from web pages via standard browsers. See * <a href=ftp://ftp.scruz.net/users/cichlid/public/x10faq> * the X10 FAQ</a> for details of the X10 protocol. * * We define the X10 commands as a set of three character ASCII strings: * a single character house code, followed by a 2 digit command code. * * Different X10 control modules have different mechanisms for interfacing * to the powerline. This abstract class encapulates the generic URL to * X10 mapping. Concrete classes are expected to take the X10 mapping, * and do what is needed to communicate that command to a particular * device. * * The handler accepts 2 kinds of X10 commands: * <dl> * <dt>SendX10?NNN <dd>Sends the X10 command NNN * <dt>Notify <dd>blocks until a command is seen on the * powerline, then returns it (in NNN format) * </dl> * For each instance of this handler, * we set mutexes around each command type, to insure only one HTTP * request is pending for each type at one time. * * This handler looks for the following server properties: * <dl> * <dt>device <dd>The name of the serial port (defaults to /dev/cua/a) * <dt>prefix <dd>The url prefix * </dl> * @author Rinaldo DiGiorgio * @author Colin Stevens * @author Stephen Uhler * @version 1.0, 09/16/1998 */</i> <i>// {@name class} </i> <b>public</b> <b>abstract</b> <b>class</b> GenericX10Handler <b>implements</b> Handler<b>,</b> Runnable <b>{</b> Server server<b>;</b> <i>// our server reference </i> String propsPrefix<b>;</b> <i>// our prefix into the server properties </i> <b>public</b> <b>static</b> <b>final</b> String DEVICE = "device"<b>;</b> <i>// the serial port to talk x10 to </i> <b>public</b> <b>static</b> <b>final</b> String PREFIX = "prefix"<b>;</b> <i>// out url prefix </i> <b>private</b> <b>static</b> <b>final</b> <b>int</b> MAX_Q = 50<b>;</b> <i>// max Q size </i> <i>// {@name mutex} </i> <i>/** * Create mutex objects, one for each command type; */</i> <b>private</b> <b>final</b> Object sendMutex = <b>new</b> Object<b>(</b><b>)</b><b>;</b> <b>private</b> <b>final</b> Object notifyMutex = <b>new</b> Object<b>(</b><b>)</b><b>;</b> Vector queue = <b>new</b> Vector<b>(</b><b>)</b><b>;</b> <i>// The X10 response Q for Notify requests </i> <b>static</b> Vector cmdList = <b>new</b> Vector<b>(</b><b>)</b><b>;</b> <i>// List of valid X10 commands </i> <i>// {@name commands} </i> <i>/** * The list of valid X10 commands. This defines the command interface to * X10, and is subject to change! */</i> <b>static</b> <b>{</b> cmdList<b>.</b>addElement<b>(</b>"01"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"02"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"03"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"04"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"05"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"06"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"07"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"08"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"09"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"10"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"11"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"12"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"13"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"14"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"15"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"16"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"A0"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"BR"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"DI"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"HR"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"L0"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"L1"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"OF"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"ON"<b>)</b><b>;</b> cmdList<b>.</b>addElement<b>(</b>"SR"<b>)</b><b>;</b> <b>}</b> <i>// {@name run} </i> <i>/** * Listen for asynchronous powerline commands. * Start a background thread to listen for commands arriving * asynchronously from the powerline, and put them on a Queue. */</i> <b>public</b> <b>void</b> run<b>(</b><b>)</b> <b>{</b> <b>while</b> <b>(</b>true<b>)</b> <b>{</b> <b>try</b> <b>{</b> String s = getCommand<b>(</b><b>)</b><b>;</b> <b>synchronized</b> <b>(</b>queue<b>)</b> <b>{</b> queue<b>.</b>addElement<b>(</b>s<b>)</b><b>;</b> <b>if</b> <b>(</b>queue<b>.</b>size<b>(</b><b>)</b> > MAX_Q<b>)</b> <b>{</b> log<b>(</b>"Q too big"<b>)</b><b>;</b> queue<b>.</b>removeElementAt<b>(</b>0<b>)</b><b>;</b> <b>}</b> queue<b>.</b>notifyAll<b>(</b><b>)</b><b>;</b> <b>}</b> <b>}</b> <b>catch</b> <b>(</b>IOException e<b>)</b> <b>{</b> <i>// ignore </i> <b>}</b> <b>}</b> <b>}</b> <i>// {@name init} </i> <i>/** * Make sure we can communicate with the X10 device, and start the * background thread. */</i> <b>public</b> <b>boolean</b> init<b>(</b>Server server<b>,</b> String prefix<b>)</b> <b>{</b> propsPrefix = prefix<b>;</b> <b>this</b><b>.</b>server = server<b>;</b> String deviceName = server<b>.</b>props<b>.</b>getProperty<b>(</b>propsPrefix + DEVICE<b>,</b> "/dev/cua/a"<b>)</b><b>;</b> <b>if</b> <b>(</b>!open<b>(</b>deviceName<b>)</b><b>)</b> <b>{</b> log<b>(</b>"Failed to open " + deviceName<b>)</b><b>;</b> <b>return</b> false<b>;</b> <b>}</b> <b>else</b> <b>{</b> log<b>(</b>"Opening " + deviceName<b>)</b><b>;</b> Thread listener = <b>new</b> Thread<b>(</b><b>this</b><b>)</b><b>;</b> listener<b>.</b>setDaemon<b>(</b>true<b>)</b><b>;</b> listener<b>.</b>start<b>(</b><b>)</b><b>;</b> <b>return</b> true<b>;</b> <b>}</b> <b>}</b> <i>/** * Get the sub-command name. X10 url's have the form: * urlPrefix/command?x10 * where: * <dl> * <dt>urlPrefix <dd> the url prefix, such as /X10/ * <dt>command <dd> the command class, either "SendX10" or "Notify" * <dt>x10 <dd> the command to send to the powerline * </dl> * <pre> * Example: /X10/SendX10?AON turns the selected unit for * house code "A" on. * * * @param request the http request * @return true – request was completely handled */ // {@name respond} public boolean respond(Request request) throws IOException { String urlPrefix = request.props.getProperty(propsPrefix + PREFIX, “/X10/”); if (!request.url.startsWith(urlPrefix)) { log(“Not my prefix: ” + request.url); return false; } // {@name parse} StringTokenizer fields = new StringTokenizer(request.url.substring(1), “/”); String command; // our X10 command class try { fields.nextToken(); // skip the prefix command = fields.nextToken(); } catch (NoSuchElementException e) { request.sendError(404, “No X10 command supplied”); return true; } if (fields.hasMoreTokens()) { request.sendError(404, “Sub-commands are not supported”); return true; } log(“Args=” + request.query + ” Command=” + command); // {@name send} /* * Check the command for validity, and send it to the powerline. */ if (command.equals(“SendX10”)) { synchronized (sendMutex) { String query = request.query.toUpperCase(); char houseCode = query.charAt(0); if (query.length() != 3) { request.sendError(404, “Invalid Query length (must be 3)”); } else if (houseCode ‘P’) { request.sendError(404, “Invalid housecode, not A-P”); } else if (!cmdList.contains(query.substring(1))) { request.sendError(404, “Invalid cmd, try: ” + cmdList); } else { sendCommand(query); request.sendResponse(“ok=” + query, “text/plain”); } } // {@name notify} /* * Wait until a command appears on the powerline, * then deliver it. */ } else if (command.equals(“Notify”)) { synchronized (notifyMutex) { try { synchronized (queue) { while (queue.size() == 0) { queue.wait(); } request.sendResponse((String) queue.elementAt(0), “text/plain”); queue.removeElementAt(0); } } catch (InterruptedException e) { request.sendError(500, e.toString()); } } } else { request.sendError(404, “Invalid command: ” + command); } return (true); } // {@name log} /** * Convenience class for logging server messages. * @param message The message to log on the console */ protected void log(String message) { server.log(null, Server.LOG_INFORMATIONAL, propsPrefix + ” :” + message); } // {@name abstract} /** * Open the X10 device. * An attempt should be made to communicate with the device . * This is called once for each device (in init). The implementation may * consult with this.Server and this.propsPrefix if any device * specific info needs to be extracted from the server properties. * @params deviceName: The name of the X10 device to open * @returns true, if the X10 device is responding properly */ protected abstract boolean open(String deviceName); /** * Close the X10 device * Currently, this is never called. */ protected abstract void close(); /** * Return an asynchronous powerline command. * This is expected to block until a command is read from the * powerline. The 3-letter (2-way style) X10 command is returned. * This is called repeatedly by the handler if any clients are * waiting for notification. It normally blocks waiting for * input from the X10 device controller. * * @return The 3 letter X10 command */ protected abstract String getCommand() throws IOException; /** * Send an X10 command to the powerline. * Every reaonable attempt (e.g. retries) should be made to actually * deliver the command successfully. * @param command The 3-letter X10 command to send to the * powerline (in 2-way format) */ protected abstract void sendCommand(String command) throws IOException; } TwoWayHandler.javaThis second file is the implementation of the interface required to support a specific interface to the power line, like a TW523. The documentation contains pointers to more information. <b>package</b> sunlabs<b>.</b>brazil<b>.</b>x10<b>;</b> <b>import</b> java<b>.</b>io<b>.</b>DataInputStream<b>;</b> <b>import</b> java<b>.</b>io<b>.</b>IOException<b>;</b> <b>import</b> java<b>.</b>io<b>.</b>OutputStream<b>;</b> <b>import</b> javax<b>.</b>comm<b>.</b>CommPortIdentifier<b>;</b> <b>import</b> javax<b>.</b>comm<b>.</b>SerialPort<b>;</b> <i>/** * Two-way X10 protocol handler for the X10 PowerHouse TW523. * Implement a handler for the PowerHouse TwoWay X10 to TW523 device. * See the <a href=http://www.smarthome.com/1135f.html> PowerHouse * </a> site for more details. * * This communicates with the device using javax.comm over a serial port. * @author Rinaldo DiGiorgio * @author Colin Stevens * @author Stephen Uhler * @version %V% 99/08/06 */</i> <b>public</b> <b>class</b> TwoWayHandler <b>extends</b> GenericX10Handler <b>{</b> OutputStream output<b>;</b> <i>// output to serial port </i> DataInputStream input<b>;</b> <i>// input from serial port </i> SerialPort port<b>;</b> <i>// the serial port the 2way is on. </i> <b>byte</b><b>[</b><b>]</b> data = <b>new</b> <b>byte</b><b>[</b>4<b>]</b><b>;</b> <i>// The 2way command output buffer </i> <i>/** * Open the 2way device Make sure we can talk to it. * * @param name Port to Open. * * @return success or failure * * @see */</i> <b>protected</b> <b>boolean</b> open<b>(</b>String name<b>)</b> <b>{</b> <b>try</b> <b>{</b> CommPortIdentifier id = CommPortIdentifier<b>.</b>getPortIdentifier<b>(</b>name<b>)</b><b>;</b> port = <b>(</b>SerialPort<b>)</b> id<b>.</b>open<b>(</b>"X10SerialInterface"<b>,</b> 2000<b>)</b><b>;</b> port<b>.</b>setSerialPortParams<b>(</b>2400<b>,</b> SerialPort<b>.</b>DATABITS_8<b>,</b> SerialPort<b>.</b>STOPBITS_2<b>,</b> SerialPort<b>.</b>PARITY_NONE<b>)</b><b>;</b> port<b>.</b>setFlowControlMode<b>(</b>SerialPort<b>.</b>FLOWCONTROL_NONE<b>)</b><b>;</b> input = <b>new</b> DataInputStream<b>(</b>port<b>.</b>getInputStream<b>(</b><b>)</b><b>)</b><b>;</b> output = port<b>.</b>getOutputStream<b>(</b><b>)</b><b>;</b> <i>/* * Try to communicate with the device */</i> <b>byte</b><b>[</b><b>]</b> send = <b>{</b> <b>(</b><b>byte</b><b>)</b> 'r' <b>}</b><b>;</b> <b>byte</b><b>[</b><b>]</b> recv = <b>new</b> <b>byte</b><b>[</b>2<b>]</b><b>;</b> port<b>.</b>enableReceiveTimeout<b>(</b>2000<b>)</b><b>;</b> <b>for</b> <b>(</b><b>int</b> i = 1<b>;</b> i < 4<b>;</b> i++<b>)</b> <b>{</b> log<b>(</b>"Sent Hello to " + name + " (" + i + ")"<b>)</b><b>;</b> output<b>.</b>write<b>(</b>send<b>)</b><b>;</b> output<b>.</b>flush<b>(</b><b>)</b><b>;</b> <b>int</b> got = input<b>.</b>read<b>(</b>recv<b>)</b><b>;</b> log<b>(</b>"Got " + got + " bytes"<b>)</b><b>;</b> <b>if</b> <b>(</b>got >= 1 && recv<b>[</b>0<b>]</b> == '?'<b>)</b> <b>{</b> log<b>(</b>"2-way OK"<b>)</b><b>;</b> port<b>.</b>enableReceiveTimeout<b>(</b>20000<b>)</b><b>;</b> <i>// could block forever </i> <b>return</b> true<b>;</b> <b>}</b> <b>}</b> <b>}</b> <b>catch</b> <b>(</b>Exception e<b>)</b> <b>{</b> <i>// javax.comm.NoSuchPortException </i> <i>// javax.comm.PortInUseException </i> <i>// javax.comm.UnsupportedCommOperationException </i> <i>// java.io.IOException </i> log<b>(</b>"Error contacting " + name + " " + e<b>)</b><b>;</b> <b>}</b> log<b>(</b>"Can't talk to " + name<b>)</b><b>;</b> <b>return</b> false<b>;</b> <b>}</b> <i>/** * Close the port * */</i> <b>protected</b> <b>void</b> close<b>(</b><b>)</b> <b>{</b> port<b>.</b>close<b>(</b><b>)</b><b>;</b> <b>}</b> <i>/** * Send an X10 command to the 2-way. The Command is almost already * in 2-way format, we just need to add a r. * * @param command a command like set HouseCode or Unit Code * * @exception IOException * */</i> <b>protected</b> <b>void</b> sendCommand<b>(</b>String command<b>)</b> <b>throws</b> IOException <b>{</b> command += "r"<b>;</b> command<b>.</b>getBytes<b>(</b>0<b>,</b> 4<b>,</b> data<b>,</b> 0<b>)</b><b>;</b> output<b>.</b>write<b>(</b>data<b>)</b><b>;</b> output<b>.</b>flush<b>(</b><b>)</b><b>;</b> <i>/* * The 2-way loses data if you talk to it too fast */</i> <b>try</b> <b>{</b> Thread<b>.</b>sleep<b>(</b>1000<b>)</b><b>;</b> <b>}</b> <b>catch</b> <b>(</b>InterruptedException e<b>)</b> <b>{</b> log<b>(</b>"Sleep interrpted: " + e<b>)</b><b>;</b> <b>}</b> <b>}</b> <i>/** * Read data from the powerline. * * @return the command form the Power line interface * * @exception IOException * * @see */</i> <b>protected</b> String getCommand<b>(</b><b>)</b> <b>throws</b> IOException <b>{</b> <b>while</b> <b>(</b>true<b>)</b> <b>{</b> String s = input<b>.</b>readLine<b>(</b><b>)</b><b>;</b> <b>if</b> <b>(</b>s != <b>null</b><b>)</b> <b>{</b> log<b>(</b>"From PL: " + s<b>)</b><b>;</b> <b>}</b> <b>if</b> <b>(</b>s != <b>null</b> && s<b>.</b>length<b>(</b><b>)</b> > 0 && s<b>.</b>charAt<b>(</b>0<b>)</b> > 31<b>)</b> <b>{</b> <b>return</b> <b>(</b>s<b>.</b>substring<b>(</b>1<b>)</b><b>)</b><b>;</b> <b>}</b> <b>}</b> <b>}</b> <b>}</b> ConclusionWe have shown how to interface three different devices to the Web using the UPI approach, and we have shown that UPI complements Jini. In the introduction, we claimed that the UPI technology is easier, cheaper, and more malleable than current proprietary approaches. In the article, we also discussed some very simple handlers that can easily be expanded to support more features, such as providing the average temperature in a home, or the status of all devices on the network. These handlers can be used by folks having experience only with JavaScript and HTML, as well as by Java programmers. The UPI approach requires a minimal footprint, neutralizes browser differences, and includes support of security models.Rinaldo Di Giorgio has been involved in the creation of a smart card URL programming interface that integrates OpenCard with the Web. He is also working on a Jini-aware Java Card infrastructure and technology for easily interfacing other devices such as X10 and weather stations to the Web. Di Giorgio has been working with Java Card technology for three years, is currently writing a book on Java Card, and is a regular column author for JavaWorld. Software DevelopmentAccess ControlJava