Using the X-10 Schedule Toy Program

This describes how to use the demo program "X-10 Schedule Toy", whose main class is found in app.x10toy.ScheduleToy.

Program Startup

The main window initially appears with its list contents loaded from two text-files: If you edit these files according to the instructions
given below and summarized in each file's comments, you can define your own X-10 devices and scheduled actions as the defaults.

You can find other examples in the text files of the "Examples" folder. Some of these illustrate the built-in localization features using French and Spanish day-names. Pardonnez-moi, but my French isn't good enough to provide editing instructions en Français. And my Spanish is even worse.

The HubIO and serial-port name are not persistent. You must set them each time you run the program. You can remove or reorder the available options by editing and recompiling the ScheduleToy source file. If you want your serial-port choice to persist, you'll have to write some code yourself. You may have to modify or sub-class one or more of the provided classes. This is one feature that distinguishes a toy from a real product.

If you choose the "Serial port" option but no serial-port choices appear, it's probably because you didn't install the Java-Comm JAR for your platform. Or your class-path could be set wrong. Or you don't have any serial-ports on your machine.

Main Program Window

The exact appearance of your main program window may differ from this example, depending on the fonts in your system, the platform you run it on, the serial-port names, etc.

Screen shot

The left-hand list contains the X-10 Gadgets, the right-hand list contains the scheduled actions. Below the left-hand list are "activation" buttons just like in the Bathtub Toy demo program. Below the activation buttons is the choice, button, and sub-options for selecting the CP290 I/O connection. The choices are fewer than in the Bathtub Toy, and "Serial port" is the default. Note that your choice of serial-port still does not persist. The first port-name shown is simply the first one that Java-Comm returned. Also note the default HubIO is still set to HexHubIO, not SerialHubIO. So you must still choose a HubIO when you start the program.

Other than being above the HubIO chooser and having a "Gadgets" label, the Gadget-list is identical to the one in the Bathtub Toy. It's filled from a different text-file, however, so you will see different Gadgets listed.

The right-hand list contains scheduled actions, listed by name. Since the name is also the scheduled alarm-time, you can tell when an action will occur simply by looking at it. The list is not sorted, and appears in the same order as you defined the scheduled actions in the file.

The File menu consists of

When you select a file to load, it will automatically go into the Gadgets list if it has the suffix ".x10", or into the Schedule list if it has the suffix ".when". Files with any other suffix are ignored. Reloading the Schedule list has no effect on the Gadgets list. Reloading the Gadgets list, however, will clear the Schedule list, and discard all the scheduled actions that were there. This is done because a scheduled action relies on the names of the X-10 Gadgets, and if you replace the Gadgets then previously scheduled actions are no longer valid.

The syntax of the gadget and schedule files is described below, and summarized in the default files themselves. The schedule-file syntax is highly configurable, and can easily be localized for day-names in different languages without recompiling anything.

On Mac OS, the "About this Program..." menu-item under the Apple menu shows a dialog with the name of the program and my web-page URL in it. Click "OK" to dismiss the dialog.

Typical Operation

  1. Ensure that your CP290 is connected to a serial-port of the computer.
  2. Ensure that you have a Java-Comm JAR for your computer properly installed. (Mac OS users: one is provided. It will work where it is.)
  3. Start the Schedule Toy program.
  4. Choose "Serial ports" and then choose the serial-port name that your CP290 is connected to.
  5. Click the "Set HubIO to:" button.
  6. Observe that a message appears in the console-out window, beginning with the text "Hub ping response:" followed by an English day-name, a time-of-day in 24-hour form, and a letter A-P.
  7. Also observe that the class-name at bottom-left becomes "glguerin.gadget.hub.SerialHubIO".
  8. You may now control X-10 modules as you wish, or manually trigger the scheduled actions, or watch them as their alarms go off.
If you click the "Set HubIO to:" button and instead see a message like "Hub ping response: ## Ping failed: ..." then the CP290 is not responding on the serial-port. Check the cable, software, chosen port-name, etc. before trying again. Diagnosing serial-port failures is highly platform-dependent, and I can't offer detailed help.

The Gadgets List and HubIO Chooser

The lower part of the window contains a choice and a button, a sub-panel below them, and a label with a class-name. You should use these elements when you start the program, choosing the I/O method and serial-port connected to your CP290.

When you choose from the available items, the sub-panel's contents change to reflect a possible sub-option for that particular kind of item. If there are no sub-options, a constant string appears in the sub-panel. For example, the "Hex to console" item has no sub-options and displays "...to console". The "Serial port" item, however, presents another choice where each item is the name of an available serial-port. Choosing items from the main choice or from sub-options have no effect until you click the "Set HubIO to:" button. Thus, you can safely browse all available options and sub-options.

When you click the "Set HubIO to:" button, the HubIO is set and a "ping" is sent to the Hub. If the ping succeeds, the returned String appears in the console window. In any case, the resulting class-name of the active HubIO is displayed in the text below the sub-options sub-panel. Once it's set to talk to a valid CP290 device, you won't have to change the setting until the next time you run the program.

The upper part of the window contains the Gadget list and "activation buttons" that affect the selected list-items. Double-clicking a list-item toggles the state of the selected items. The levels associated with the "L", "M", and "H" buttons are defined by an array of 3 floats (i.e. normalized values). You can change these by editing and recompiling the BathtubToy source file. The "+" and "-" buttons incrementally increase or decrease the level of the selected items. Each Gadget is independently adjusted. These incremental commands each take about 10 seconds or so for the CP290 to complete, so don't expect an immediate change in the controlled device, even though the list item shows an immediate change in value.

When you press the buttons on the CP290 itself, the changes are reflected in the list items. List items also change when a scheduled-event in the CP290's event-list is triggered, or when an item in the Schedule list observes that its alarm-time has arrived or you manually trigger it.

The Schedule List

Schedule List items represent a scheduled time at which a defined set of actions will occur. The entire set of actions occurs either when the scheduled time arrives or when you manually trigger them.

When a Schedule item detects that its alarm-time has arrived, it quietly triggers its actions. This occurs quickly, since all the commands produced are put into a queue that trickles out to the CP290 controller as it completes prior queued commands. Manually activating the Gadgets in the Gadgets List also puts commands into the queue. The queue-length expands as needed.

When a Schedule item detects its alarm-time, it enters the ALARMED state, triggering the actions. It also changes its appearance in the Schedule list, prepending a "#" during the one-minute period the alarm remains active. The targeted Gadgets also change their list appearance. Note that only the transition into the alarmed state triggers the actions. A transition out of the alarmed state only changes the Schedule item's appearance back to normal.

You can also manually trigger a Schedule item. Double-clicking a Schedule item shows its information on console out and then triggers the actions. Double-clicking produces exactly the same result as if you selected a Schedule item, clicked the "See it" button, then clicked the "Do it" button. You can manually trigger the actions many times. They will trigger again when its alarm-time arrives. Manual triggering has no effect on the detection of the alarm-time.

Multiple Schedule items can be in the ALARMED state at the same time. However, you can only select one Schedule item from the list at a time. This is different from the Gadgets list, where you can select multiple items at the same time. This difference is intentional.

When you click the "See it" button, or double-click a scheduled item, a text summary of it appears on console out. This summary does not appear when a Schedule item detects its own alarm-time. This text is not the same form that you used to define the schedule-item in the loadable text file. It looks like this:

#Gadget: 20:02
  value: 08:50 (530)
  alarm: [1202...1202]
  Listeners... 
    <ActionAdds:-0.1[Lights]>
    glguerin.gadgetry.awt.GadgetList[list0,0,27,253x244,selected= 20:02]
The name of the Gadget is on the first line. This also represents it's alarm-time. The value of the Gadget, as you would expect, is the current time-of-day within the overall cycle. Here you can see that it was 8:50 AM on my machine, which is 530 minutes past midnight. This value will advance at one minute intervals for the MinuteOfWeek varieties of Gadgets.

The alarm-range is the number of minutes from the start of the cycle at which the action will occur. It always appears as a Range with lower and upper end-points identical. In the MinuteOfWeek Gadgets, this means that a Gadget will be in the ALARMED state for a period of one minute. The exact numbers displayed depend on the locale (more info below), since they are measured from the start of the cycle, which may be locale-dependent. The alarm-values are always displayed numerically. A little arithmetic should show that the Gadget's name determines its alarm-time.

The Listeners are listed one per line. Each action-set you defined will appear on its own line between <> symbols to mark it as a GadgetTrigger-derived listener. The action-type is shown, followed by the parameter value, ending with the list of target Gadgets between []'s. The information displayed is not parseable as an action-set.

You'll also see a line showing the fact that the GadgetList itself is listening for events. That's how it knows to redraw items that enter or leave the ALARMED state.

File Formats

The "X-10 Schedule Toy" program reads text files. From the text it defines Gadgets representing your X-10 modules, and it creates scheduled times at which those modules are activated in ways you define.

There is no easy interactive way to define X-10 modules or schedules -- only the text files. That's one difference between a toy and a real product.

Gadget Definitions

Gadget definitions for X-10 modules are provided in a text file whose name has the suffix ".x10". Gadgets are listed one per line, in the form:
/deviceID=name for lamp (dimmable) modules
deviceID=name for appliance (on/off) modules
Leading and trailing white-space on the line is ignored, as is white-space on either side adjacent to the "=". White-space embedded within the name is kept, and will prevent the Gadget from being named in a scheduled action.

Empty (blank) lines are ignored. Lines that have '#' as the first non-white-space character are also ignored as comments.

A Gadget's type and device-ID appear first on the line. The type is "/" for lamp (dimmable) modules, or nothing for appliance (on/off) modules. The device-ID is a house-code letter in the range A-P followed by:

a single unit-code in the range 1-16,
or by a comma-separated list of unit-codes (each 1-16),
or by a "*" character to mean "all units with this house-code".
WARNING: This use for "*" truly means EVERY unit, and includes every appliance and lamp unit with that house-code. The ALL-LIGHTS-ON code is not available and can't be used. You should be very careful turning on "*" Gadgets that have appliance-modules controlling motorized devices.

Following the type and device-ID is an "=" and the name as it will appear in the list. The name can have embedded blanks or any other displayable character, and continues until the end of line. Leading and trailing white-space in a name are trimmed, but embedded white-space is retained. Non-ASCII characters in the name are read according to the default encoding for Reader classes on your platform. For Mac OS versions in North America and Western Europe, this is the MacRoman interpretation. For Windows, I suspect it's the ISO-8859-1 (ISO-Latin-1) interpretation. The default interpretation is given by the value of the "file.encoding" system property for your platform.

The same Gadget-type and device-ID can be repeated with a different name, perhaps in a form acceptable to a scheduled-time action. For example, you can have one name with embedded white-space and another name without, both referring to the same type and device-ID. All repetitions will appear in the Gadget list, and don't count as duplicates.

Scheduled Actions

The schedule file contains text with the same basic line-parsing rules as the Gadget definitions. Scheduled times, targets, and actions are provided in a text file whose name has the suffix ".when". Empty (blank) lines in the file are ignored. Lines that have '#' as the first non-white-space character are also ignored as comments.

A schedule-file must contain at least one factory designation before any scheduled times appear. An optional locale designation may also appear, as explained in more detail below. A factory designation looks like this:

factory = fully.qualified.classname
The keyword "factory" followed by "=" and a fully qualified class-name adds a factory to the head of the internal factory-list. A fully qualified class-name means the complete package-name and class-name, using the correct case. It's a class-name, not a file-name, so don't include ".class".

The designated factory will be responsible for recognizing and parsing all the scheduled times that follow it in the file. If you don't designate at least one factory, then your scheduled times will not be recognized, and you'll see a series of errors on console out. Two factory classes are provided:

After you designate at least one factory, you then list the scheduled times and the actions that occur at that time. Each scheduled time appears on its own line, in the form:
time=actions
time is a time-of-day, with an optional, possibly localized, leading day-name abbreviation.
actions is a series of one or more action-sets, separated by white-space, each action-set containing target Gadget-names and a single command.
Leading and trailing white-space on the line is ignored, as is white-space on either side adjacent to the "=". White-space separates the actions, too, which prevents Gadget-names whose names have embedded white-space from being the targets of actions.

The scheduled time can be a time-of-day alone, or a week-day name followed by a time-of-day. A lone time-of-day represents an action with a daily cycle -- it will trigger every day at that time. Including the week-day name (actually, abbreviation) gives the action a weekly cycle -- it will trigger only on that one day and time.

Here are some examples of scheduled times and the circumstances under which they are valid:

Note that the above have no special meaning or significance. They are just the forms that the MinuteOfWeek factories recognize. If you create a different factory and designate it in the file, then you can recognize any format you want, or even supplant the formats shown above with your own interpretation.

Unlike with Gadget definitions, it's not uncommon for the same scheduled time to be repeated with different actions. They will all trigger at the same time, and their actions will occur in order of triggering. There are very few guarantees about triggering order. The only reliable behavior is that for a list of actions given on one line, i.e. at a single scheduled time, the actions will occur in the given order. There is no guarantee that other simultaneously triggered action-sets won't interleave themselves. There is no guarantee that a manually initiated action won't appear amidst the given sequence. There is no guarantee that a timed event in the CP290 itself won't occur at the same time, possibly garbling the outcome.

Each action-set in the list of actions consists of one or more target Gadget-names and a single command in this form:

names:command
names is a single Gadget-name, or a comma-separated list of names.
command is a command-name (e.g. OFF or ON), or a number indicating a value.
The target Gadget-names MUST NOT contain embedded white-space or the colon character (:). Embedded white-space will cause the parser to divide up the action-sets at the wrong places. Names with colons in them will cause the parser to separate the names from the command at the wrong place.

All targets must be the names of items in the Gadgets list, not the device-ID's. Every target must be a name. You can't refer to X-10 modules that haven't been defined and given a name. The target names are case-insensitive.

For the following examples, assume that the Gadgets list contains items that have been named with their house-code and unit-code. These examples illustrate the options available for the command, not the naming of X-10 Gadgets:

Because one scheduled time can have any number of actions that fit on the same line, you can set some modules off, some on, some dimmed, etc. The target Gadgets named in each action-set can be from different house-codes -- each target will receive individual X-10 commands. Also recall that a single Gadget can represent multiple units that have the same house-code. This represents only a single Gadget as far as the scheduled time is concerned.

International Features

Both the Gadget definitions and the schedule have localization options. There is far more flexibility in defining the schedule, though.

Both kinds of files can contain non-ASCII (i.e. "high ASCII") characters. For example, a Gadget-name may include an accented letter or a special punctuation symbol like the inverted question-mark. These are interpreted according to the default character-encoding for Java InputStreamReaders -- that is, the value of the "file.encoding" property.

I've only tested with a few non-English Roman-alphabet languages, though, so there could be bugs in my code for dealing with this. If the accented characters you type in aren't appearing correctly, however, check that your "file.encoding" property is set to the encoding-name that your text-files assume. For Mac OS versions in North America and Western Europe, this should be "MacRoman" or "MacTEC" (MRJ defaults to the latter). For Windows versions using the Roman alphabet, this property should probably be "8859_1". Whatever encoding the property designates, your JVM must have the necessary resources. Sun's JRE may provide English-only support. Check with your JVM vendor for its support of international text encodings, especially if you are using a non-Roman writing system.

The schedule file greatly expands this localization, using the default locale to determine the recognized day-name abbreviations, the AM/PM symbols, and the first-day-of-week convention. You can also force a specific locale to be used, such as Canadian-French, Mexican-Spanish, or UK-English. Furthermore, you can even support more than one language at the same time, as long as the day-name abbreviations are unambiguously recognizable.

An even greater degree of configurability is available when a Java program uses the Gadget-Kit classes directly. Among other things, you can control the names of the ON/OFF commands, the delimiters separating actions and targets, the key-words for designating a factory and locale, the distinguishing file-suffixes, and so on. See the source code and API docs for details.

A schedule-file must contain at least one factory designation before any scheduled times appear. It may contain an optional locale designation, which must also appear before any scheduled times. It usually appears before the factory designation, if it appears at all. A locale designation and factory designation look like this:

locale = localeCode
factory = fully.qualified.classname
The keyword "locale" followed by "=" and a localeCode sets the language and country-code for all subsequent factory designations. The localeCode is a typical Java-locale abbreviation, such as: You must have a JVM that contains the localization resources for any locale you designate. Sun's JDK distributions typically include all localizing and internationalization resources, but their JRE distributions may include only a subset (e.g. only North-American English resources). Check with your JVM provider. The localization resources available in your JVM may also affect which text-encodings you can use.

The keyword "factory" followed by "=" and a fully qualified class-name adds a factory to the head of the internal factory-list. A fully qualified class-name means the complete package-name and class-name, using the correct case. It's a class-name, not a file-name, so don't include ".class".

When a scheduled time is parsed from a line, the factory-list is walked from head to tail, asking each factory if it recognizes the character-sequence. The first factory to recognize it is then asked to create an object whose alarm that will trigger at the represented time. The factories only create scheduled-time objects -- they do not parse the action-sets.

You can designate multiple factories in a single file. They can have different cycle-lengths, tick-intervals, etc. If a scheduled time is ambiguous, i.e. could be meaningful to more than one factory, the first one to recognize it will produce the object. Since factories are walked in order from newest to oldest, you can arrange the order of factory designators in your file to obtain any behavior you like.

A couple of factory classes are provided (also see the examples):

Of course, you can define your own factories and use them, too. You may not even need to modify or recompile the Schedule Toy program. Just ensure that the additional classes are in the class-path.

Platform Notes

If you have additional serial-ports on your machine, you should see them in the "Serial ports" sub-option choice. This software has been tested on a Macintosh with a 4-port PCI-card, and it works fine. Your serial-ports must install Comm ToolBox (CTB) drivers, but as long as they do that you should see them. Even "shadow" serial-ports or port-emulators that work over USB should appear as long as the CTB driver is properly installed.

If you change the system clock on your machine in order to observe scheduled items triggering, you may see that there is some time lag between when you change the clock and when the Java program notices the change. This occurs because some JVM's will cache an internal value for the system clock and increment it at intervals, rather than always calling on the OS to determine the system time. The purpose is to avoid a costly system-call for what occurs rapidly -- namely, the ticking of the clock. JVM's that do this will periodically resynchronize to the system clock, but they may only do this every 30 seconds or so. Thus, it may take a little while for your changes to the system clock to propagate into the Java programs.

Mac OS users can load files using the Finder's drag-n-drop feature exactly as if the "Load gadgets or schedule..." menu item had been chosen. Just drag a text-file containing Gadget definitions or scheduled times onto the program's Finder icon, drop it, and the program will load the file as if you had used the menu item and chosen a file in the ensuing dialog. Any text file will work, including one from SimpleText. You can even use different fonts, styles, etc. in SimpleText files. Only the actual text will be used to define Gadgets or scheduled times.

When you drag-n-drop a text file onto the program's Finder icon, it will automatically go into the Gadgets list if it has the suffix ".x10", or into the Schedule list if it has the suffix ".when". Files with any other suffix are ignored. Just as with the menu-item, reloading the Gadgets list will clear the Schedule list.

Mac OS users will notice that the fonts used in the main program window do not follow the fonts you selected in the Appearance control panel. Instead, they are always Geneva and Courier. This is intentional, and avoids a sporadic bug with relying on default fonts. If you want to change it, rebind the programs and remove the awt.font properties.