Skip to content

Commit

Permalink
[somfytahoma] Setting of channels at init + UoM for channels (openhab…
Browse files Browse the repository at this point in the history
…#10300)

Fix openhab#10291
Fix openhab#10285

Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo authored Mar 14, 2021
1 parent 18ccada commit 443f93c
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,30 @@
import java.util.List;
import java.util.Map;

import javax.measure.Unit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaDevice;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaState;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaStatus;
import org.openhab.core.library.types.*;
import org.openhab.core.thing.*;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.thing.binding.builder.ThingBuilder;
Expand All @@ -38,6 +56,7 @@
* The {@link SomfyTahomaBaseThingHandler} is base thing handler for all things.
*
* @author Ondrej Pecta - Initial contribution
* @author Laurent Garnier - Setting of channels at init + UoM for channels
*/
@NonNullByDefault
public abstract class SomfyTahomaBaseThingHandler extends BaseThingHandler {
Expand All @@ -46,23 +65,57 @@ public abstract class SomfyTahomaBaseThingHandler extends BaseThingHandler {
private HashMap<String, Integer> typeTable = new HashMap<>();
protected HashMap<String, String> stateNames = new HashMap<>();

protected String url = "";

private Map<String, Unit<?>> units = new HashMap<>();

public SomfyTahomaBaseThingHandler(Thing thing) {
super(thing);
// Define default units
units.put("Number:Temperature", SIUnits.CELSIUS);
units.put("Number:Energy", Units.WATT_HOUR);
units.put("Number:Illuminance", Units.LUX);
units.put("Number:Dimensionless", Units.PERCENT);
}

public HashMap<String, String> getStateNames() {
return stateNames;
}

protected String url = "";

@Override
public void initialize() {
url = getURL();
if (getThing().getProperties().containsKey(RSSI_LEVEL_STATE)) {
createRSSIChannel();
Bridge bridge = getBridge();
initializeThing(bridge != null ? bridge.getStatus() : null);
}

@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
initializeThing(bridgeStatusInfo.getStatus());
}

public void initializeThing(@Nullable ThingStatus bridgeStatus) {
SomfyTahomaBridgeHandler bridgeHandler = getBridgeHandler();
if (bridgeHandler != null && bridgeStatus != null) {
url = getURL();
if (getThing().getProperties().containsKey(RSSI_LEVEL_STATE)) {
createRSSIChannel();
}
if (bridgeStatus == ThingStatus.ONLINE) {
SomfyTahomaDevice device = bridgeHandler.getCachedDevice(url);
if (device != null) {
updateUnits(device.getAttributes());
List<SomfyTahomaState> states = device.getStates();
updateThingStatus(states);
updateThingChannels(states);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, UNAVAILABLE);
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
}
updateStatus(ThingStatus.ONLINE);
}

private void createRSSIChannel() {
Expand Down Expand Up @@ -178,11 +231,49 @@ protected void cacheStateType(String stateName, int type) {
}
}

private void updateUnits(List<SomfyTahomaState> attributes) {
for (SomfyTahomaState attr : attributes) {
if ("core:MeasuredValueType".equals(attr.getName()) && attr.getType() == TYPE_STRING) {
switch ((String) attr.getValue()) {
case "core:TemperatureInCelcius":
case "core:TemperatureInCelsius":
units.put("Number:Temperature", SIUnits.CELSIUS);
break;
case "core:TemperatureInKelvin":
units.put("Number:Temperature", Units.KELVIN);
break;
case "core:TemperatureInFahrenheit":
units.put("Number:Temperature", ImperialUnits.FAHRENHEIT);
break;
case "core:RelativeValueInPercentage":
units.put("Number:Dimensionless", Units.PERCENT);
break;
case "core:LuminanceInLux":
units.put("Number:Illuminance", Units.LUX);
break;
case "core:ElectricalEnergyInWh":
units.put("Number:Energy", Units.WATT_HOUR);
break;
case "core:ElectricalEnergyInKWh":
units.put("Number:Energy", Units.KILOWATT_HOUR);
break;
case "core:ElectricalEnergyInMWh":
units.put("Number:Energy", Units.MEGAWATT_HOUR);
break;
default:
logger.warn("Unhandled value \"{}\" for attribute \"core:MeasuredValueType\"", attr.getValue());
break;
}
break;
}
}
}

protected @Nullable State parseTahomaState(@Nullable SomfyTahomaState state) {
return parseTahomaState(null, state);
}

protected @Nullable State parseTahomaState(@Nullable String acceptedState, @Nullable SomfyTahomaState state) {
protected @Nullable State parseTahomaState(@Nullable String acceptedItemType, @Nullable SomfyTahomaState state) {
if (state == null) {
return UnDefType.NULL;
}
Expand All @@ -205,14 +296,32 @@ protected void cacheStateType(String stateName, int type) {
switch (type) {
case TYPE_PERCENT:
Double valPct = Double.parseDouble(state.getValue().toString());
if (acceptedItemType != null && acceptedItemType.startsWith(CoreItemFactory.NUMBER + ":")) {
Unit<?> unit = units.get(acceptedItemType);
if (unit != null) {
return new QuantityType<>(normalizePercent(valPct), unit);
} else {
logger.warn("Do not return a quantity for {} because the unit is unknown",
acceptedItemType);
}
}
return new PercentType(normalizePercent(valPct));
case TYPE_DECIMAL:
Double valDec = Double.parseDouble(state.getValue().toString());
if (acceptedItemType != null && acceptedItemType.startsWith(CoreItemFactory.NUMBER + ":")) {
Unit<?> unit = units.get(acceptedItemType);
if (unit != null) {
return new QuantityType<>(valDec, unit);
} else {
logger.warn("Do not return a quantity for {} because the unit is unknown",
acceptedItemType);
}
}
return new DecimalType(valDec);
case TYPE_STRING:
case TYPE_BOOLEAN:
String value = state.getValue().toString();
if ("String".equals(acceptedState)) {
if ("String".equals(acceptedItemType)) {
return new StringType(value);
} else {
return parseStringState(value);
Expand Down Expand Up @@ -247,9 +356,11 @@ private State parseStringState(String value) {
switch (value.toLowerCase()) {
case "on":
case "true":
case "active":
return OnOffType.ON;
case "off":
case "false":
case "inactive":
return OnOffType.OFF;
case "notdetected":
case "nopersoninside":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
Expand All @@ -35,9 +40,25 @@
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.somfytahoma.internal.config.SomfyTahomaConfig;
import org.openhab.binding.somfytahoma.internal.discovery.SomfyTahomaItemDiscoveryService;
import org.openhab.binding.somfytahoma.internal.model.*;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaAction;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaActionGroup;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaApplyResponse;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaDevice;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaEvent;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaLoginResponse;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaRegisterEventsResponse;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaSetup;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaState;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaStatus;
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaStatusResponse;
import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.*;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
Expand Down Expand Up @@ -106,6 +127,9 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
*/
private String eventsId = "";

private ExpiringCache<List<SomfyTahomaDevice>> cachedDevices = new ExpiringCache<>(Duration.ofSeconds(30),
this::getDevices);

// Gson & parser
private final Gson gson = new Gson();

Expand Down Expand Up @@ -331,6 +355,16 @@ public List<SomfyTahomaDevice> getDevices() {
return response != null ? List.of(response) : List.of();
}

public synchronized @Nullable SomfyTahomaDevice getCachedDevice(String url) {
List<SomfyTahomaDevice> devices = cachedDevices.getValue();
for (SomfyTahomaDevice device : devices) {
if (url.equals(device.getDeviceURL())) {
return device;
}
}
return null;
}

private void getTahomaUpdates() {
logger.debug("Getting Tahoma Updates...");
if (ThingStatus.OFFLINE == thing.getStatus() && !reLogin()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* to TahomaLink account.
*
* @author Ondrej Pecta - Initial contribution
* @author Laurent Garnier - Add attributes data
*/
@NonNullByDefault
public class SomfyTahomaDevice {
Expand All @@ -33,6 +34,7 @@ public class SomfyTahomaDevice {
private String oid = "";
private SomfyTahomaDeviceDefinition definition = new SomfyTahomaDeviceDefinition();
private List<SomfyTahomaState> states = new ArrayList<>();
private List<SomfyTahomaState> attributes = new ArrayList<>();

public String getLabel() {
return label;
Expand Down Expand Up @@ -61,4 +63,8 @@ public SomfyTahomaDeviceDefinition getDefinition() {
public List<SomfyTahomaState> getStates() {
return states;
}

public List<SomfyTahomaState> getAttributes() {
return attributes;
}
}

0 comments on commit 443f93c

Please sign in to comment.