RapidConnect Simple Java Host: Startup Guide




Overview

This page will demonstrate how to write Java code in order to interact with a RapidConnect module.

The tutorial has been developed to run on Windows, macOS, and Linux.

By the end of this tutorial:

  • You'll be able to write code that will send and receive frames to and from a RapidConnect Module over the serial port.
  • You'll be introduced to more advanced concepts such as
    • Configuring the Device

    • Forming a Network

    • Controlling a Simple Device

This tutorial will refer to the sample code provided here: rapid-connect-simple-java-host-2.0.0.zip. The sample code has been designed to provide users with an application that they can reference for developing their own Host application. It is packaged as an Eclipse project, or you can use Java on the command line to compile and run, as long as you set the proper class-path.




Getting Started

Requirements

You'll need:

  1. macOS, Windows, or Linux environment that can run Java.
  2. Java Runtime Environment, version 1.8 or higher.
  3. RapidConnect USB Stick or Development Board, running RapidHA version 1.5.7 or higher.
  4. Eclipse Java IDE

Importing the project into Eclipse

  1. Download and unzip the sample project: rapid-connect-simple-java-host-2.0.0.zip
  2. Open Eclipse
  3. Go to File → Import
  4. Expand the 'General' folder and select 'Existing Projects into Workspace' from the list
  5. Browse to the project folder and select it, then finish importing the project.
  6. To run the project, right click the 'rapidconnect-simple-java-host.launch' configuration file from the 'Project Explorer' view, and select Run As → rapidconnect-simple-java-host
    1. The project requires an argument to know which serial port to connect to
    2. The default argument is /dev/tty.SLAB_USBtoUART
    3. To change the default argument, right click the project, go to Properties → Run/Debug Settings → Edit → Arguments, and change accordingly

Exploring the Project

Main.java

This file contains the entry point to the program and starts a very simple command line interface. Its purpose is to demonstrate how one might use the Host class in their application.

Host.java

This file encapsulates the logic required to communicate with the Module. It contains a SerialDriver to handle the communication with the serial port, and a single-threaded event-loop that handles each frame received from the Module.

This is where you'd write most of your logic to send messages and handle responses.

SerialDriver.java

This class covers serial communication between the host and the module. It handles the sending and receiving of frames as well as implementing the Serial Acknowledgment algorithm.

This class can be used as-is, and doesn't need to be modified.

StartupSyncStateMachine.java

This class performs the device configuration sequence, and demonstrates important topics such as the startup sync sequence, setting device type, endpoint configuration, and registering passthroughs. An overview of these topics can be found here. By default, the device is configured as a Full Functional Device with various client-side clusters. This setup is ideal for control of devices on the network.

This is where you'd modify your device configuration by adding clusters and attributes.

SerialUpgradeStateMachine.java

This class is responsible for initiating and completing a serial upgrade by implementing the logic described in the Firmware Upgrades page of the Serial Protocol.

The Host class contains an instance of this object and manages it throughout its lifecycle.

DeviceTable.java

This class contains a method stub designed to show you how new devices joining your network could be handled.

You could modify this file to keep track of all devices that have joined your network.

ClusterCommands.java

This class provides sample code for constructing ZCL Commands. In this sample we use the On/Off cluster commands to demonstrate building custom ZCL frames with demonstrable results. Connect a certified device with On/Off cluster support to your network and view the results of sending the On/Off cluster commands.

You could modify this file to add more helper methods to construct commands.




Quick Demo

Before we begin writing any code, we'll first try to connect to an MMB Module, form a network, and try to control a ZigBee certified light.

Connecting the Sample Host to your MMB Module

The Sample Host takes one argument. This argument is the serial port identifier for your MMB Device. For example, on macOS or Linux it could be '/dev/tty.SLAB_USBtoUART'. On Windows, it could be "COM1".

When the Sample Host is run it will automatically open a serial connection to the device and configure the device as a Full Functional Device with some client clusters. You can see all of the clusters that are configured by going to the StartupSyncStateMachine class → endPointConfig() function.

Example Output
Open Serial Port: /dev/tty.SLAB_USBtoUART
Done connecting.
TX: RHASerialACKConfigWrite :[ F1 55 30 00 01 01 87 00 ]
RX: RHAStatusResponse :[ F1 55 80 00 01 00 D6 00 ]
Enter a command: 
RX: RHAStartupSyncRequest :[ F1 55 21 84 02 00 01 FD 00 ]
TX: RHAStatusResponse :[ F1 55 80 84 01 00 5A 01 ]
TX: RHASerialACKConfigWrite :[ F1 55 30 01 01 01 88 00 ]
RX: RHAStatusResponse :[ F1 55 80 01 01 00 D7 00 ]
TX: RHAHostStartupReady :[ F1 55 20 02 00 77 00 ]
RX: RHAStartupSyncRequest :[ F1 55 21 85 02 00 01 FE 00 ]
TX: RHAStatusResponse :[ F1 55 80 85 01 00 5B 01 ]
TX: RHAAddEndpoint :[ F1 03 10 03 1E 01 04 01 07 00 01 02 00 00 03 00 09 00 00 03 00 04 00 05 00 06 00 08 00 01 01 01 02 02 02 73 00 ]
RX: RHAStatusResponse :[ F1 55 80 03 01 00 D9 00 ]
TX: RHAStartupSyncComplete :[ F1 55 22 04 00 7B 00 ]
RX: RHAStatusResponse :[ F1 55 80 04 01 00 DA 00 ]
RX: RHANetworkStatusResponse :[ F1 01 09 86 10 01 00 19 00 00 BF CC 86 4A 75 C4 1E B9 59 7C 00 FA 05 ]
TX: RHAStatusResponse :[ F1 55 80 86 01 00 5C 01 ]

Forming a Network

Type 'f' to form a network when prompted to enter a command.

Form Network Output
Enter a command: f
TX: RHAFormNetwork :[ F1 01 01 06 0F 00 F8 FF 07 03 FF FF FF FF FF FF FF FF FF FF 0E 0C ]
RX: RHANetworkStatusResponse :[ F1 01 09 88 10 03 FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 9F 06 ]
TX: RHAStatusResponse :[ F1 55 80 88 01 00 5E 01 ]
RX: RHAStatusResponse :[ F1 55 80 06 01 00 DC 00 ]
RX: RHANetworkStatusResponse :[ F1 01 09 89 10 01 00 19 00 00 D7 D8 1E E7 52 7A 0E 26 AC B8 00 D5 05 ]
TX: RHAStatusResponse :[ F1 55 80 89 01 00 5F 01 ]

Permit Join

Type 'p' to open the Permit Join Window for 30 seconds.

Permit Join Output
Enter a command: p
TX: RHAPermitJoin :[ F1 01 03 09 01 1E 2C 00 ]
RX: RHANetworkStatusResponse :[ F1 01 09 8D 10 01 00 10 00 00 A8 84 B8 E5 78 0F 11 A6 64 C5 1E 06 06 ]
TX: RHAStatusResponse :[ F1 55 80 8D 01 00 63 01 ]
RX: RHAStatusResponse :[ F1 55 80 09 01 00 DF 00 ]

Join a Device

Join a device (during the window where permit join is open) using its commissioning process. Take note of the device Node ID when it connects.

Join Device Output
RX: RHATrustCenterDeviceUpdate :[ F1 01 10 90 0D FA A6 7E 37 0F 00 00 46 24 00 00 00 00 7C 03 ]
TX: RHAStatusResponse :[ F1 55 80 90 01 00 66 01 ]
RX: RHAZDODeviceAnnounceReceived :[ F1 04 1E 91 0B FA A6 7E 37 0F 00 00 46 24 00 8E 1A 04 ]
TX: RHAStatusResponse :[ F1 55 80 91 01 00 67 01 ]
---> Device has joined the network <---
---> Node Id: a6fa
---> EUI64: 00244600000f377e
---> Device Type: Full Functionality Device

Send a Command to the Remote Device

Type 'c' to get into the On/Off command cluster menu. Follow the prompts to send On, Off or Toggle commands to your light device.

Sending a Command Output
Enter a command: c
Enter NodeID: 
a6fa
Enter Endpoint: 
1
Type ON for On Command, OFF for Off command, TOG for Toggle command: 
on
TX: RHASendZCLUnicast :[ F1 05 00 0B 0E FA A6 01 01 06 00 00 00 11 00 00 00 01 00 D8 01 ]
RX: RHAZCLSendStatus :[ F1 05 03 0B 02 00 01 16 00 ]
TX: RHAStatusResponse :[ F1 55 80 0B 01 00 E1 00 ]




Advanced

Now that we've performed a simple demo, we can begin to explore the Sample Host to see how it works.

Establishing Serial Communications

The sample Host creates an instance of the SerialDriver, which is used to send/receive frames to/from the Module. It is instantiated as follows:

SerialDriver Instantiation
public Host(final String portName) throws HostInitializationException {
    mSerialDriver = new SerialDriver(portName);
    boolean connected = mSerialDriver.connect();
    if (!connected) {
        throw new HostInitializationException("Problem Connecting to port" + portName);
    }
     mSerialDriver.registerEventQueue(mEventQueue);
...
}

Note that in order to receive frames from the SerialDriver, you must use the registerEventQueue function. All received serial frames will be queued here for the Host application to process however it chooses to do so.

In the sample Host, this queue is processed in its own thread:

EventHandler Thread
@Override
public void run() {
    mEventLoopRunning.set(true);

    // single-threaded event loop that will handle messages off the serial handler
    while (mEventLoopRunning.get()) {
        try {
            // will block here until there's something in the queue
            final Object o = mEventQueue.take();

            // handle frames
            if (o instanceof ARHAFrame) {
				// frame handling logic here
            }
        
        } catch (InterruptedException th) {
            // ignore
        }
    }

    System.out.println("Quitting EventHandler...");
}

Configuring the Device

The Sample Host comes with a very simple state machine that is triggered by the RHAStartupSyncRequest frame from the Module (see EventHandler code above).

See the deviceTypeConfig() and endpointConfig() methods for examples of how to configure device type, endpoints, and attributes.

See the transitionTo method to see how to register passthroughs.

Forming a Network

You can form a network by sending the RHAFormNetwork frame:

Form Network
public void formNetwork() {
	final RHAFormNetwork req = new RHAFormNetwork();

	// set all channels
	Bitmap32 channelMask = new Bitmap32();
	for (int i = 11; i < 27; i++) {
	    channelMask.setBit(i);
	}
	req.setChannelMask(channelMask);

	// auto-everything
	req.setAutoOptions(new Bitmap8(new byte[] {0x03}));
	req.setShortPANID(new PanId());
	req.setExtendedPANID(new ExtendedPanId());

	// send message
	serial.sendMessage(req);
}

Sending and Receiving Frames

The Java Serial Library contains Java objects that wrap the Serial Protocol (there is one object for each frame), and can be used to send frames and parse received frames. You can see the javadoc here.

For example, to send a Module Info Request:

Send Frame
...
mSerialDriver.sendMessage(new RHAModuleInfoRequest());
...

The sendMessage function will allow you to send frames to the Module from any thread. Responses will be queued up in the queue that was registered with the SerialDriver when it was constructed, and can be handled by the Host however it chooses.

In the sample Host, all received messages are handled by the EventHandler class, which processes the mEventQueue on its own thread. You could add your message handling code here:

Receive Frame
// in the event handler run loop
...
if (o instanceof RHAModuleInfoResponse) {
	final RHAModuleInfoResponse res = (RHAModuleInfoResponse)o;
	final String version = res.getMajorFirmwareVersion().toString() + "." + res.getMinorFirmwareVersion().toString() + "." + res.getBuildFirmwareVersion().toString();
	System.out.println("Firmware Version: " + version);
}
...

Serial Upgrade

Performing a serial upgrade can be done by calling the following method on the Host class:

Serial Upgrade
...
host.startSerialUpgrade(filePath);
...

The Host will update its SerialUpgradeStateMachine from the event-loop thread. The Host has two methods that will be called updating it with the status of the upgrade: notifyUpgradeSuccess and notifyUpgradeFailed.




Exporting a Runnable JAR

You can export the project to a runnable standalone JAR file, which can be run on a Linux, macOS, or Windows platform, by following these steps:

  1. Right-click the project in Eclipse, and select "Export..."
  2. Select "Runnable JAR"
  3. Choose Launch Configuration "Host - rapid-connect-simple-java-host"
  4. Select an Export Destination
  5. For the Library Handling option, ensure that "Extract required libraries into generated JAR" is selected
  6. Click Finish
  7. You can run the jar using the following command: java -jar <jarname.jar> </path/to/device>

For example, on Linux, you can run java -jar <jarname.jar> /dev/ttyUSB0




Conclusion

This tutorial has demonstrated how to use the Java Serial Libraries to establish serial communications with the device, configure the device, form networks, send and receive frames, and control a simple remote device. It has been developed to run on most platforms that support the JRE, such as Windows, macOS, and Linux - but the concepts learned in this tutorial could be used to program on most any other platform.




Legal Notices

Copyright © 2018 MMB Networks, Inc. All rights reserved.

Confidential materials prepared and delivered by MMB Networks for receipt and review only by any partner subject to a valid and enforceable MMB Networks confidentiality agreement. Any receipt, review, or misuse of any of the content exchanged hereunder by any party not a party to this confidential exchange shall be subject to any and all rights available under the law. All rights, title and interest to the materials shall remain with MMB Networks.

Any suggestions provided to MMB Networks with respect to MMB Networks' products or services shall be collectively deemed “Feedback.” You, on behalf of yourself, or if you are providing Feedback on behalf of your employer or another entity, represent and warrant that you have full legal authority to bind such entity to these terms, agree to grant and hereby grant to MMB Networks a nonexclusive, perpetual, irrevocable, royalty free, worldwide license to use and otherwise exploit such Feedback within any MMB Networks products and services.

Legal Notices

Copyright © 2020 MMB Networks, Inc. All rights reserved.
Confidential materials prepared and delivered by MMB Networks for receipt and review only by any partner subject to a valid and enforceable MMB Networks confidentiality agreement. Any receipt, review, or misuse of any of the content exchanged hereunder by any party not a party to this confidential exchange shall be subject to any and all rights available under the law. All rights, title and interest to the materials shall remain with MMB Networks.
Any suggestions provided to MMB Networks with respect to MMB Networks' products or services shall be collectively deemed “Feedback.” You, on behalf of yourself, or if you are providing Feedback on behalf of your employer or another entity, represent and warrant that you have full legal authority to bind such entity to these terms, agree to grant and hereby grant to MMB Networks a nonexclusive, perpetual, irrevocable, royalty free, worldwide license to use and otherwise exploit such Feedback within any MMB Networks products and services.