Managing device definitions - GideonLeGrange/panstamp-java GitHub Wiki

Device definitions supplement what is known about a panStamp node, it's registers and endpoints. As such, device definitions are key to the panStamp system, since without them, a server application will not know what the data sent and received by a device means.

Definitions are typically provided by XML files which are loaded from a directory tree and parsed. By default, the library uses a copy of the public XML definitions (downloaded from here) which is loaded from the panstamp-java jar file using the Java class loader. This was done so that new developers can use the standard panStamp sketches without having to worry about providing XML definitions. It is, however, not ideal for the following reasons:

  • The definitions are not necessarily up to date with what is in the public repository (since they are stored in the jar)
  • Definitions for user written sketches aren't in the jar.
  • Advanced developers may not want to use XML definitions, but may prefer some other format.

To avoid these problems, and to allow developers to write useful applications, the following options for providing definitions are available:

  • Advanced XML loaders are provided, and can be configured to control definition loading.
  • Custom XML loaders can be written to load definitions in an application specific way, while still using the built-in XML parser.
  • It is also possible to implement device definitions in a way that does not require XML at all. Currently examples of this is not provided. Anybody wishing to try this, must start by implementing DeviceLibrary from scratch.

Using the provided XML library implementations

The abstract XML implementation of the DeviceLibrary is called XmlDeviceLibrary, and the following useful subclasses are provided:

  • ClassLoaderLibrary - Loads XML device definitions using the Java class loader. This is the default implementation used if the user does not supply a device library. It is already set up when you create a Network.
  • FileLibrary - Loads XML device defintions from files in a directory.
  • HttpLibrary - Loads XML device defintions from a web site.

It is important to understand that all the XML library implementations expect the XML files to be in a "directory" hierachy with devices.xml in the "root" and subdirectories for different manufacturers; basically the structure as seen in the panStamp repository.

The FileLibrary

To use the FileLibrary loader, simply instantiate it tell the Network to use it by calling setDeviceLibrary. FileLibrary requires a Java File instance pointing to the directory containing the definition hierarchy:

	// assume we have a network called nw. 
	// we want to access XML definitions from /usr/local/panstamp/definitions using the file system
	nw.setDeviceLibrary(new FileLibrary(new File("/usr/local/panstamp/definitions")));

The HttpLibrary

The example for HttpLibrary is similar; the difference is that it is constructed using a URL object:

	nw.setDeviceLibrary(new HttpLibrary(new URL("https://raw.githubusercontent.com/panStamp/panstamp/master/devices/")));

:warning: This implementation does not cache definitions to local disc, and is not efficient. While it will work, it will make your application slow.

Writing a custom XML loader

To create an application specific XML loader, simply extend XmlDeviceLibrary and provide an implementation of getStream(String path) that will return an XML definition's text as an InputStream based on the path specified. A working examples of this, comes from FileLibrary:

	@Override
    InputStream getStream(String path) {
        try {
            return new FileInputStream(dir.getAbsolutePath() + "/" + path);
        } catch (FileNotFoundException ex) {
            log.warning(String.format("File '%s' for does not exist under '%s'.", path, dir.getAbsolutePath()));
            return null;
        }
    }

It is important to note that if the named resource cannot be found, getStream() is expected to return null. Logging an error is a good idea.

Chaining multiple device libraries

It possible to use multiple device libraries to find device definitions. One reason to do this, would be to allow users to add their locally stored, personal definitions to an application (by for example storing them in a configuration directory) while using the standard panStamp definitions for devices running the standard sketches.

To achieve this, we provide library implementation called CompoundDeviceLibrary which is constructed with all the device library to search as parameters. Example:

    nw.setDeviceLibrary(new CompoundDeviceLibrary(
		new FileLibrary(new File("/usr/local/panstamp/definitions")), 
		new ClassLoaderLibrary()));
	

The devices libraries provided to CompoundDeviceLibrary are searched in the order provided.