Personal Universal Controller Communications Protocol

Documentation originally by Michael Higgins.

Protocol design by the Personal Universal Controller working group: Michael Higgins, Joe Hughes, Peter Lucas, Brad A. Myers, Jeffrey Nichols, and Mathilde Pignol.

Table of Contents

  1. Introduction
  2. Revision History
  3. Conceptual Basis
  4. Message Enumeration
    1. Controller Generated Messages
    2. Appliance Generated Messages
  5. Wire Format For Messages Over Plain TCP/IP
  6. DTD
  7. Future Work
  8. Example

Introduction

The personal universal controller (PUC) project's goal is to build a software framework running on top of a personal digital assistant (PDA) that is capable of providing an interface that will allow users to control any appliance within their environment. In essence, the PUC is a device-independent, appliance-independent, user-dependent remote control device.

For more information about the PUC framework, see the Personal Universal Controller home page. You may also be interested in the appliance specification language.

This document describes the high-level communications protocol used by the Personal Universal Controller and the appliances it is controlling. It does not describe the physical transport layer or a service discovery protocol.

Revision History

Date Name Comments
03/07/2002 higgins First version.
03/11/2002 jwn Minor modifications prior to posting the document on the web and adding it to the cvs repository.

Conceptual Basis

Because the Personal Universal Controller has few pre-conceived notions of what sort of devices may be controlled or, indeed, what form the controller may take, the communications protocol must be quite general. To achieve this it has been kept simple, with a minimum of messages.

Our protocol assumes a connection-oriented transport underneath it, though because it is mostly asynchronous it could probably be easily adapted to connection-less environment or even a broadcast environment. We have implemented it over TCP/IP.

XML is used for the general syntax to achieve harmony with the specification language. This may also allow easy adaptation for use with SOAP and other emerging XML communication standards.

Typically, the appliance acts as a server, waiting for controllers to establish connections. The controller is not required to send any particular message upon establishing the connection, but typically it immediately performs a spec-request to establish the states available and their types. It then performs a full-state-request to get the complete state of the appliance. This allows the controller to build an interface reflecting the current state of the appliance.

The most interesting feature of the protocol is that it is mostly asynchronous. The appliance can emit a state-change-notification at any time; typically, the controller does not poll for state changes. If the controller suspects that it has gotten out of sync with the appliance state, it can issue a full-state-request.

The controller can issue a state-change-request at any time. There is no explicit acknowledgement of this by the appliance, but typically a state-change-notification will happen shortly thereafter (reflecting successful change of state according to the request).

The controller should be prepared to receive unasked-for "responses" such as a device-spec message at any time as well.

The reason for this asynchronous design is that many appliances may change independently of the controller (typically as a result of some internal event, like the completion of a long-running chore, or because of some other command, like the manipulation of the physical controls on the device). Furthermore many real-world state changes take significant time to complete. The protocol should not artificially prevent the controller from issuing other requests or receiving other notifications while one transaction is occurring. It is also possible that we may wish to interleave many controller-appliance relationships over one transport connection. An asynchronous design helps facilitate all of these.

Message Enumeration

The controller should be prepared to receive any appliance-generated message at any time, and to wait indefinitely for an appliance-generated message. In particular, the controller should not expect a strict request-response discipline to be maintained.

Likewise, the appliance must be prepared to receive any controller-generated message at any time.

Controller Generated Messages

state-change-request
This message requests the appliance to change the designated state to the value contained in the message.
command-invoke-request
This message requests the appliance to invoke a command. This may cause state changes as side effects.
spec-request
This message requests the appliance to send a copy of its specification. It will send this via the device-spec message.
full-state-request
This message requests the appliance to send state-change-notification messages for every state it has.

Appliance Generated Messages

state-change-notification
This message is sent whenever the appliance changes state. The state name as well as its value is sent.
device-spec
This message contains the appliance specification. It is sent after receiving a spec-request message.

It is likely that additional messages will be added as the PUC project evolves.

Wire Format For Messages Over Plain TCP/IP

Each message is an XML document formatted according to the DTD specified below. Plain TCP/IP has no convenient mechanism for specifying message length, so you must prefix the message with a four byte LSB signed two's-complement integer encoding the length of the message in bytes.

Immediately following the length encoding is a well-formed XML document conforming to the following DTD and containing the header

<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
	

DTD

<!-- This is version 0.1 of the Personal Universal Controller -->
<!-- Protocol Specification Document Type Definition -->

<!ELEMENT message (state-change-request | spec-request | full-state-request | state-change-notification | device-spec | command-invoke-request)>

<!ELEMENT state-change-request (state-name, value)>

<!ELEMENT command-invoke-request (command-name)>

<!ELEMENT spec-request EMPTY>

<!ELEMENT full-state-request EMPTY>

<!ELEMENT state-change-notification (state-name, value)>

<!ELEMENT device-spec (spec)>

<!ELEMENT state-name (#PCDATA)>

<!ELEMENT command-name (#PCDATA)>

<!ELEMENT value (#PCDATA)>

<!-- Include the DTD for the appliance specification language, -->
<!-- which forms the contents of the device-spec element -->

<!ENTITY % pucspec SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucspec.dtd">

%pucspec;
      

Future Work

There is no heartbeat present in the communications spec, so a controller cannot easily tell the difference between an appliance that has crashed and one that is merely slow. If the protocol is implemented in a connection-oriented environment the dropping of the connection could be used to indicate this, but that may not be a reliable indicator of the appliance's health. Many wireless environments have poor quality-of-service guarantees, so should be expected to suffer connection failures and congestion. The current workaround for this is to periodically have the controller perform a full-state-request. If no response is had within some reasonable time, the appliance can be assumed dead. Because the response to a full-state-request is typically large this is a somewhat unsatisfactory approach.

There is no service discovery aspect to the protocol. We assume that some other mechanism is being used to identify controllable resources nearby. The reason we have left this critical feature out of the communications protocol is that it interacts strongly with the choice of physical transport. Infrared transports have very limited discovery options (either the appliance you point the controller at is controllable or it's not). Bluetooth wireless networks have their own service discovery scheme; other wireless networks require one to be layered on top.

In the future it is likely that the contents of the value element will be a more complex structure rather than simple PCDATA.

It is likely that we will add features that allow the controller to query an appliance about datatypes that it cannot understand. The idea is that there will be a small set of universally understood types. Other types will be constructed from those primitives (and perhaps add some lightweight semantics). Controllers that understand the high-level types will be able to efficiently download specs. Simpler controllers will have to perform a negotiation process with the appliance, in which the primitives for a given high-level type are revealed.

Example

For the sake of a simple example, we'll imagine using the PUC to control a lamp. (The lamp is the "appliance".)

Initially, the lamp is off. A user walks up to it, armed with a PUC, and initiates communication.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <spec-request/>
</message>
    

The lamp responds with a spec.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <device-spec>
       <spec name="lamp">
           <groupings>
              <group>
                <state name="PowerState" priority="10">
                 <type name="OnOffType">
                  <valueSpace>
                   <boolean/>
                  </valueSpace>
                  <valueLabels>
                   <map index="false">
                    <label>Off</label>
                   </map>
                   <map index="true">
                    <label>On</label>
                   </map>
                  </valueLabels>
                 </type>

                 <labels>
                  <label>Power</label>
                  <label>Powr</label>
                  <label>Pwr</label>
                 </labels>
                </state>
              </group>
           </groupings>
       </spec>
   </device-spec>
</message>
    

This response contains the complete spec for the lamp, which is quite simple. It contains one boolean state, indicating the power. Upon receiving it, the controller asks for a report on the lamp's complete state.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <full-state-request/>
</message>
    

In response, the lamp indicates that it is off. Only one state is transmitted because there is only one state.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <state-change-notification>
     <state-name>
      PowerState
     </state-name>
     <value>false</value>
   </state-change-notification>
</message>
    

Now the user will turn the light on using the PUC.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <state-change-request>
     <state-name>
      PowerState
     </state-name>
     <value>true</value>
   </state-change-request>
</message>
    

The lamp turns itself on, and as a consequence of the state change, sends a message indicating its new state.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <state-change-notification>
     <state-name>
      PowerState
     </state-name>
     <value>true</value>
   </state-change-notification>
</message>
    

Meanwhile, the user's mother decides that it's time for all good little users to go to bed, so she flips off the lightswitch on the lamp. Now the lamp asynchronously reports the state change so that the PUC can redraw its interface.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message SYSTEM "http://www.cs.cmu.edu/~jeffreyn/controller/pucprotocol.dtd">
<message>
   <state-change-notification>
     <state-name>
      PowerState
     </state-name>
     <value>false</value>
   </state-change-notification>
</message>
    

Michael Higgins
Last modified: Mon Mar 11 15:09:06 EST 2002