Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In the following example, we also pass in a lambda an instance of a class that implements the DeviceEventHandler interface, that will handle device events by simply discovering them and printing them out. In a real application, you can replace this with your own event handling method, or an object that implements the DeviceEventListener interfaceout their properties.

Code Block
languagejava
titleInitializing GatewayClient
linenumberstrue
// exampleExample of creating a lambda implementation GatewayClient object with an instance of the DeviceEventListenerSampleDeviceEventHandler parameter.class
final GatewayClient gwgateway = new GatewayClient( new ConnectionInfo(ConnectionType.ZIGBEE_UART, "/dev/ttyS1"), new SampleDeviceEventHandler() );


The following is an example of a class that implements the DeviceEventHandler interface. It contains one method that must be implemented to handle when devices are added to, or removed from, the network.

Code Block
languagejava
titleSampleDeviceEventHandler
linenumberstrue
public class SampleDeviceEventHandler implements DeviceEventHandler {
    
    private final SamplePropertyUpdateHandler propertyHandler;
    
    public SampleDeviceEventHandler() {
        this.propertyHandler = new SamplePropertyUpdateHandler();
    }

    @Override
    public void onDeviceEvent(DeviceEvent event) {
        // This method gets called when a device is added to, or removed from, the network.
        // By default, client callbacks are called from a single thread managed by GAPI.
        // Therefore, avoid writing blocking code in this method, or other client callbacks
        // (such as PropertyUpdateHandlers, or ProtocolHandlers) may be blocked.
        
        final DeviceEventStatus eventStatus = event.getStatus();
        final Device device = event.getDevice() -> {;
        final String deviceId = device.getID();
        final String deviceType = device.getDeviceType().getType();
        
        System.out.println("Device Event: " + event.getStatus() eventStatus);
        System.out.println("Device Id: " + deviceId);
        System.out.println("Device Type: " + event.getDevice().getID());
    }
); deviceType);
        
        switch (eventStatus) {
        
        case DEVICE_ADDED:
            // Register a property handler, to be notified when a Property on the Device changes.
            device.addPropertyUpdateHandler(propertyHandler);
            
            // Automatically discover the device. This is a non-blocking call.
            CompletableFuture<Collection<Property>> properties = device.getProperties();
            
            // Do some extra (asynchronous) handling on the properties, once they've been discovered.
            properties.thenAccept( collection -> {
                // This code will be called from a thread managed by GAPI.
                // We should avoid writing blocking code in this section.
                for (Property p : collection) {
                    printDiscoveredProperty(p);
                }
            });

            break;

        case DEVICE_REMOVED:
            break;

        default:
            break;
        }
    }
    
    private static void printDiscoveredProperty(Property p) {
        StringBuilder sb = new StringBuilder();
        sb.append("Discovered Property: ").append(p.getName())
          .append(", with value: ").append(p.getValue())
          .append(", of type: ").append(p.getType());
        System.out.println(sb.toString());
    }
}


Once constructed, the GatewayClient will automatically connect to the device, configure it as a Combined Interface, and form a network. If it can't connect to or configure the device, it will throw a GatewayConnectionException.

It will call the SampleDeviceEventHandler.onDeviceEvent(DeviceEvent event) method whenever a Device is detected on the network (i.e. added to the network), or whenever a device leaves the network.

Scanning for Devices

To join a device to the network, you first have to open the permit join window on the GatewayClient.

...

Code Block
languagejava
titleScanning for Devices (i.e. opening the permit join window)
linenumberstrue
for (ConnectionInfo c: gwgateway.getConnectionInfo()) {
    gwgateway.scanForDevices(c, 30).thenAccept( status -> {
        System.out.println("Status for connection " + c.getValue() + " is " + status);
    });
}

...

When a device joins the network, you should see a DeviceEvent. For example, the lambda SampleDeviceEventHandler we passed into GatewayClient should print something like the following:

Code Block
Device Event: ADDDEVICE_ADDED
Device ID: 00244600000f1472_1

...

For example, to automatically discover the properties of a device the first time the GatewayClient becomes aware of it, you can run something like the following code from the DeviceEventListener DeviceEventHandler.onDeviceEvent callback:

The first time 'getProperties' is called, the system will perform a discovery of the remote device's properties over the network. This may take some time; however, any subsequent call will return once properties have been discovered, users have the option of calling 'getCachedProperties()' to get the last known value (cached) values immediately. Cached values are updated on writes, reads, and attribute reports. For more details, see the API documentation for getProperties().

Code Block
languagejava
titleDiscovering Properties
linenumberstrue
if (event.getStatus() == DeviceEventStatus.ADD) {
    final Collection<Property> properties = event.getDevice().getProperties();
    for (Property p : properties) {
        System.out.println("name: " + p.getName() + ", value: " + p.getValue() + ", type: " + p.getType());
    }
}// Automatically discover the device. This is a non-blocking call.
CompletableFuture<Collection<Property>> properties = device.getProperties();

getProperty()

You can also get specific properties using the getProperty() method. For example, to get the "OnOff" property from a LightDevice, you could do something like the following:

Code Block
languagejava
titleGetting a Property
linenumberstrue
final Property pproperty = device.getProperty("OnOffonOff").getFuture().get(5, TimeUnit.SECONDS);
System.out.println("name: " + p.getName() + ", value: " + p.getValue());

...

Code Block
languagejava
titleUpdating a Property
linenumberstrue
Property property = new Property("OnOffonOff, "boolean", "true");
gwgateway.getDevice(id).updateProperty(property);

...

Code Block
languagejava
titleLightDevice API
linenumberstrue
final Device d = gwgateway.getDevice(id);
if (d instanceof LightDevice) {
    final LightDevice light = (LightDevice) d;
    light.off();
    light.on();
	light.readLevel();
	light.moveToLevel(50);
} else {
    System.out.println("device is not a light");
}

...

Code Block
languagejava
titleThermostatDevice API
linenumberstrue
final Device d = gwgateway.getDevice(id);
if (d instanceof ThermostatDevice) {
	final ThermostatDevice device = (ThermostatDevice) d;
	device.readMode();
	device.changeMode(SystemMode.AUTO);
} else {
	System.out.println("device is not a thermostat");
}

...

You can be notified when a Property on a Device changes by registering a "Property Update ListenerHandler". In Java, this can be any object that implements the "Consumer" interface, or a lambda.

For example, to automatically register an update listener handler the first time the GatewayClient becomes aware of a device, you can run something like the following code from the DeviceEventListener callbackDeviceEventHandler.onDeviceEvent callback, from within the DEVICE_ADDED case statement:

Code Block
languagejava
titleAdding a Property Update Listener
linenumberstrue
ifdevice.addPropertyUpdateHandler(new (event.getStatus() == DeviceEventStatus.ADD) {
    final Device d = event.getDevice();
    final String deviceId = d.getID();
    d.addPropertyUpdateListener(p -> {SamplePropertyUpdateHandler());


...where SamplePropertyUpdateHandler is an instance of a class that implements the BiConsumer<Device, Property> interface. An example of which is shown below:

Code Block
languagejava
titleSamplePropertyUpdateHandler
linenumberstrue
public class SamplePropertyUpdateHandler implements BiConsumer<Device, Property> {
    @Override
    public void accept(Device device, Property property) {
        // This method gets called whenever a Property on a device changes.
        // By default, client callbacks are called from a single thread managed by GAPI.
        // Therefore, avoid writing blocking code in this method, or other client callbacks
        // (such as DeviceEventHandlers, or ProtocolHandlers) may be blocked.
        
        System.out.println("Property update triggered for device: " + deviceIddevice.getID());
        System.out.println("Property: " + pproperty.getName() + ", value: " + pproperty.getValue() + ", type: " + pproperty.getType());
    });
}


The above example will simply print out the Device IDId, as well as the Property name, value, and type, whenever the Property on that Device changes.

Enable Default Reporting

...

For example, for a LightDevice, you can enable reporting so that the device will notify the PropertyUpdateListener PropertyUpdateHandler registered above whenever its status changes.

Code Block
languagejava
titleEnable Default Reporting
linenumberstrue
final Device device = gwgateway.getDevice(idStr);
final String result = device.enableDefaultReporting().get(30, TimeUnit.SECONDS);
System.out.println("Status for command: " + result);

...

Code Block
languagejava
titleShutting down the GatewayClient
linenumberstrue
...
gwgateway.shutdown();
...

See the GatewayClient API for more details.

...

To explore further, please see the API documentation, and look at the Sample Code available on the Downloads page.

Much of the sample code referred to in this guide can be found in the Sample Code available on the Downloads page.