Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
S0urceror committed Jul 22, 2017
2 parents 056e73a + de202b4 commit a0688bc
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 103 deletions.
Expand Up @@ -69,6 +69,26 @@
</parameter>
</config-description>
</thing-type>
<thing-type id="group">
<supported-bridge-type-refs>
<bridge-type-ref id="gateway"/>
</supported-bridge-type-refs>

<label>Tradfri Group</label>
<description>A group of Tradfri lamps</description>

<channels>
<channel id="group_state" typeId="group_state"/>
</channels>

<config-description>
<parameter name="id" type="integer" required="true">
<label>ID</label>
<description>The identifier of the group on the gateway</description>
</parameter>
</config-description>

</thing-type>

<!-- note that this isn't yet supported by the code as we do not receive any data from the gateway for it -->
<thing-type id="0820" listed="false">
Expand Down Expand Up @@ -109,5 +129,11 @@
<description>Allows to control the color temperature of light.</description>
<category>ColorLight</category>
</channel-type>


<channel-type id="group_state">
<item-type>Switch</item-type>
<label>Group State</label>
<description>Allows to switch on or off all lamps in a group.</description>
</channel-type>

</thing:thing-descriptions>
Expand Up @@ -29,6 +29,8 @@ public class TradfriBindingConstants {
public final static ThingTypeUID THING_TYPE_DIMMABLE_LIGHT = new ThingTypeUID(BINDING_ID, "0100");
public final static ThingTypeUID THING_TYPE_COLOR_TEMP_LIGHT = new ThingTypeUID(BINDING_ID, "0220");
public final static ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "0820");
// Grouped lights (and maybe in the future other devices)
public final static ThingTypeUID THING_TYPE_GROUP = new ThingTypeUID(BINDING_ID, "group");

public static final Set<ThingTypeUID> SUPPORTED_LIGHT_TYPES_UIDS = ImmutableSet.of(THING_TYPE_DIMMABLE_LIGHT,
THING_TYPE_COLOR_TEMP_LIGHT);
Expand All @@ -39,6 +41,7 @@ public class TradfriBindingConstants {
// List of all Channel IDs
public static final String CHANNEL_BRIGHTNESS = "brightness";
public static final String CHANNEL_COLOR_TEMPERATURE = "color_temperature";
public static final String CHANNEL_GROUP_STATE = "group_state";

// IPSO Objects
public static final String DEVICES = "15001";
Expand Down
Expand Up @@ -7,7 +7,7 @@
*/
package org.eclipse.smarthome.binding.tradfri.handler;

import static org.eclipse.smarthome.binding.tradfri.TradfriBindingConstants.DEVICES;
import static org.eclipse.smarthome.binding.tradfri.TradfriBindingConstants.*;

import java.io.IOException;
import java.net.InetSocketAddress;
Expand Down Expand Up @@ -48,13 +48,13 @@
* sent to one of the channels.
*
* @author Kai Kreuzer - Initial contribution
* @author Mario Smit - Group Handler added
*/
public class TradfriGatewayHandler extends BaseBridgeHandler implements CoapCallback {
public class TradfriGatewayHandler extends BaseBridgeHandler {

private final Logger logger = LoggerFactory.getLogger(TradfriGatewayHandler.class);

private TradfriCoapClient deviceClient;
private String gatewayURI;
public TradfriCoapCallback devices, groups;
private DTLSConnector dtlsConnector;
private CoapEndpoint endPoint;

Expand Down Expand Up @@ -85,27 +85,47 @@ public void initialize() {
return;
}

this.gatewayURI = "coaps://" + configuration.host + ":" + configuration.port + "/" + DEVICES;
try {
URI uri = new URI(gatewayURI);
deviceClient = new TradfriCoapClient(uri);
} catch (URISyntaxException e) {
logger.debug("Illegal gateway URI `{}`: {}", gatewayURI, e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
return;
}

DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder(new InetSocketAddress(0));
builder.setPskStore(new StaticPskStore("", configuration.code.getBytes()));
dtlsConnector = new DTLSConnector(builder.build());
endPoint = new CoapEndpoint(dtlsConnector, NetworkConfig.getStandard());
deviceClient.setEndpoint(endPoint);

// setup DEVICES scanner
devices = setupScanner("coaps://" + configuration.host + ":" + configuration.port + "/" + DEVICES);
if (devices == null) {
logger.debug("Unable to scan for Tradfri DEVICES");
}
groups = setupScanner("coaps://" + configuration.host + ":" + configuration.port + "/" + GROUPS);
if (groups == null) {
logger.debug("Unable to scan for Tradfri GROUPS");
}

updateStatus(ThingStatus.UNKNOWN);

// schedule a new scan every minute
scanJob = scheduler.scheduleWithFixedDelay(() -> {
startScan();
}, 0, 1, TimeUnit.MINUTES);
if (devices != null) {
devices.startScan();
}
if (groups != null) {
groups.startScan();
}
}, 0, 60, TimeUnit.SECONDS);
}

TradfriCoapCallback setupScanner(String url) {
TradfriCoapCallback scanner = new TradfriCoapCallback();
scanner.gatewayURI = url;
try {
URI uri = new URI(scanner.gatewayURI);
scanner.client = new TradfriCoapClient(uri);
} catch (URISyntaxException e) {
logger.debug("Illegal gateway URI `{}`: {}", scanner.gatewayURI, e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
return null;
}
scanner.client.setEndpoint(endPoint);
return scanner;
}

@Override
Expand All @@ -114,9 +134,13 @@ public void dispose() {
scanJob.cancel(true);
scanJob = null;
}
if (deviceClient != null) {
deviceClient.shutdown();
deviceClient = null;
if (devices != null && devices.client != null) {
devices.client.shutdown();
devices.client = null;
}
if (groups != null && groups.client != null) {
groups.client.shutdown();
groups.client = null;
}
if (endPoint != null) {
endPoint.destroy();
Expand All @@ -125,74 +149,79 @@ public void dispose() {
super.dispose();
}

/**
* Does a request to the gateway to list all available devices/services.
* The response is received and processed by the method {@link onUpdate(JsonElement data)}.
*/
public void startScan() {
if (endPoint != null) {
deviceClient.get(new TradfriCoapHandler(this));
public class TradfriCoapCallback implements CoapCallback {
private TradfriCoapClient client;
private String gatewayURI;

/**
* Does a request to the gateway to list all available devices/services.
* The response is received and processed by the method {@link onUpdate(JsonElement data)}.
*/
public void startScan() {
if (endPoint != null) {
client.get(new TradfriCoapHandler(this));
}
}
}

/**
* Returns the root URI of the gateway.
*
* @return root URI of the gateway with coaps scheme
*/
public String getGatewayURI() {
return gatewayURI;
}
/**
* Returns the root URI of the gateway.
*
* @return root URI of the gateway with coaps scheme
*/
public String getGatewayURI() {
return gatewayURI;
}

/**
* Returns the coap endpoint that can be used within coap clients.
*
* @return the coap endpoint
*/
public CoapEndpoint getEndpoint() {
return endPoint;
}
/**
* Returns the coap endpoint that can be used within coap clients.
*
* @return the coap endpoint
*/
public CoapEndpoint getEndpoint() {
return endPoint;
}

@Override
public void onUpdate(JsonElement data) {
logger.trace("Response: {}", data);
@Override
public void onUpdate(JsonElement data) {
logger.debug("Gateway response: {}", data);

if (endPoint != null) {
try {
JsonArray array = data.getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
requestDeviceDetails(array.get(i).getAsString());
if (endPoint != null) {
try {
JsonArray array = data.getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
requestDeviceDetails(array.get(i).getAsString());
}
} catch (JsonSyntaxException e) {
logger.debug("JSON error: {}", e.getMessage());
setStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
} catch (JsonSyntaxException e) {
logger.debug("JSON error: {}", e.getMessage());
setStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
}
}

private void requestDeviceDetails(String instanceId) {
// we are reusing our coap client and merely temporarily set a sub-URI to call
deviceClient.setURI(gatewayURI + "/" + instanceId);
deviceClient.asyncGet().thenAccept(data -> {
logger.debug("Response: {}", data);
JsonObject json = new JsonParser().parse(data).getAsJsonObject();
deviceUpdateListeners.forEach(listener -> listener.onUpdate(instanceId, json));
});
// restore root URI
deviceClient.setURI(gatewayURI);
}
private void requestDeviceDetails(String instanceId) {
// we are reusing our coap client and merely temporarily set a sub-URI to call
client.setURI(gatewayURI + "/" + instanceId);
client.asyncGet().thenAccept(data -> {
logger.debug("Response: {}", data);
JsonObject json = new JsonParser().parse(data).getAsJsonObject();
deviceUpdateListeners.forEach(listener -> listener.onUpdate(instanceId, json));
});
// restore root URI
client.setURI(gatewayURI);
}

@Override
public void setStatus(ThingStatus status, ThingStatusDetail statusDetail) {
// are we still connected at all?
if (endPoint != null) {
updateStatus(status, statusDetail);
if (dtlsConnector != null && status == ThingStatus.OFFLINE) {
try {
dtlsConnector.stop();
dtlsConnector.start();
} catch (IOException e) {
logger.debug("Error restarting the DTLS connector: {}", e.getMessage());
@Override
public void setStatus(ThingStatus status, ThingStatusDetail statusDetail) {
// are we still connected at all?
if (endPoint != null) {
updateStatus(status, statusDetail);
if (dtlsConnector != null && status == ThingStatus.OFFLINE) {
try {
dtlsConnector.stop();
dtlsConnector.start();
} catch (IOException e) {
logger.debug("Error restarting the DTLS connector: {}", e.getMessage());
}
}
}
}
Expand Down

0 comments on commit a0688bc

Please sign in to comment.