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:
- macOS, Windows, or Linux environment that can run Java.
- Java Runtime Environment, version 1.8 or higher.
- RapidConnect USB Stick or Development Board, running RapidHA version 1.5.7 or higher.
- Eclipse Java IDE
Importing the project into Eclipse
- Download and unzip the sample project: rapid-connect-simple-java-host-2.0.0.zip
- Open Eclipse
- Go to File → Import
- Expand the 'General' folder and select 'Existing Projects into Workspace' from the list
- Browse to the project folder and select it, then finish importing the project.
- 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
- The project requires an argument to know which serial port to connect to
- The default argument is /dev/tty.SLAB_USBtoUART
- 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.
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.
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.
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.
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.
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:
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:
@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:
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:
... 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:
// 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:
... 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:
- Right-click the project in Eclipse, and select "Export..."
- Select "Runnable JAR"
- Choose Launch Configuration "Host - rapid-connect-simple-java-host"
- Select an Export Destination
- For the Library Handling option, ensure that "Extract required libraries into generated JAR" is selected
- Click Finish
- 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.