Skip to content

Commit

Permalink
refactor converter structure
Browse files Browse the repository at this point in the history
Signed-off-by: Laurent ARNAL <[email protected]>
  • Loading branch information
lo92fr committed Dec 16, 2024
1 parent 4b93ebc commit 29e6fd7
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 189 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,43 @@ public class SmartthingsColorConverter extends SmartthingsConverter {

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

public SmartthingsColorConverter(SmartthingsTypeRegistry typeRegistry, Thing thing) {
super(typeRegistry, thing);
public SmartthingsColorConverter(SmartthingsTypeRegistry typeRegistry) {
super(typeRegistry);
}

@Override
public String convertToSmartthings(Thing thing, ChannelUID channelUid, Command command) {
public void convertToSmartthingsInternal(Thing thing, ChannelUID channelUid, Command command) {
String jsonMsg;

if (command instanceof HSBType hsbCommand) {
double hue = hsbCommand.getHue().doubleValue() / 3.60;
double sat = hsbCommand.getSaturation().doubleValue();
int level = hsbCommand.getBrightness().intValue();

String componentKey = "main";
String capaKey = "colorControl";
String cmdName = "setColor";
String arguments = String.format("[ { 'hue':%s, 'saturation':%s }]", hue,
hsbCommand.getSaturation().intValue());
Object[] arguments = new Object[1];
ColorObject colorObj = new ColorObject();
colorObj.hue = hue;
colorObj.saturation = sat;
arguments[0] = colorObj;

jsonMsg = String.format(
"{'commands': [{'component': '%s', 'capability': '%s', 'command': '%s', 'arguments': %s }]}",
componentKey, capaKey, cmdName, arguments);
this.pushCommand(componentKey, capaKey, cmdName, arguments);

// setLevel is not working correctly on colorControl object
// call setLevel of switchLevel instead
arguments = new Object[1];
arguments[0] = level;
this.pushCommand(componentKey, "switchLevel", "setLevel", arguments);

} else {
jsonMsg = defaultConvertToSmartthings(thing, channelUid, command);
}

return jsonMsg;
}

private class ColorObject {
public Double hue = 0.0;
public Double saturation = 0.0;
}

/*
Expand All @@ -75,7 +86,7 @@ public String convertToSmartthings(Thing thing, ChannelUID channelUid, Command c
* org.openhab.binding.smartthings.internal.SmartthingsStateData)
*/
@Override
public State convertToOpenHab(Thing thing, ChannelUID channelUid, Object dataFromSmartthings) {
public State convertToOpenHabInternal(Thing thing, ChannelUID channelUid, Object dataFromSmartthings) {
// The color value from Smartthings will look like "#123456" which is the RGB color
// This needs to be converted into HSB type
if (dataFromSmartthings == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,29 @@
*/
package org.openhab.binding.smartthings.internal.converter;

import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.smartthings.internal.dto.SmartthingsArgument;
import org.openhab.binding.smartthings.internal.dto.SmartthingsAttribute;
import org.openhab.binding.smartthings.internal.dto.SmartthingsCapabilitie;
import org.openhab.binding.smartthings.internal.dto.SmartthingsCommand;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.smartthings.internal.type.SmartthingsTypeRegistry;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.NextPreviousType;
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.PlayPauseType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.RewindFastforwardType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.StringListType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;

/**
Expand All @@ -59,135 +49,68 @@ public abstract class SmartthingsConverter {

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

protected String thingTypeId;
protected SmartthingsTypeRegistry typeRegistry;
private Gson gson = new Gson();

SmartthingsConverter(SmartthingsTypeRegistry typeRegistry, Thing thing) {
thingTypeId = thing.getThingTypeUID().getId();
SmartthingsConverter(SmartthingsTypeRegistry typeRegistry) {
this.typeRegistry = typeRegistry;
}

public abstract String convertToSmartthings(Thing thing, ChannelUID channelUid, Command command);
public String convertToSmartthings(Thing thing, ChannelUID channelUid, Command command) {
convertToSmartthingsInternal(thing, channelUid, command);
String jsonMsg = getJSonCommands();
return jsonMsg;
}

public abstract State convertToOpenHab(Thing thing, ChannelUID channelUid, Object dataFromSmartthings);
public State convertToOpenHab(Thing thing, ChannelUID channelUid, Object dataFromSmartthings) {
State result = convertToOpenHabInternal(thing, channelUid, dataFromSmartthings);
return result;
}

/**
* Provide a default converter in the base call so it can be used in sub-classes if needed
*
* @param command
* @return The json string to send to Smartthings
*/
protected String defaultConvertToSmartthings(Thing thing, ChannelUID channelUid, Command command) {
String value;
public abstract void convertToSmartthingsInternal(Thing thing, ChannelUID channelUid, Command command);

if (command instanceof DateTimeType dateTimeCommand) {
value = dateTimeCommand.format("%m/%d/%Y %H.%M.%S");
} else if (command instanceof HSBType hsbCommand) {
value = String.format("[%d, %d, %d ]", hsbCommand.getHue().intValue(),
hsbCommand.getSaturation().intValue(), hsbCommand.getBrightness().intValue());
} else if (command instanceof DecimalType) {
value = command.toString();
} else if (command instanceof IncreaseDecreaseType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof NextPreviousType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof OnOffType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof OpenClosedType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof PercentType) {
value = command.toString();
} else if (command instanceof PointType) { // There is not a comparable type in Smartthings, log and send value
logger.warn(
"Warning - PointType Command is not supported by Smartthings. Please configure to use a different command type. CapabilityKey: {}, capabilityAttribute {}",
thingTypeId, channelUid.getId());
value = command.toFullString();
} else if (command instanceof RefreshType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof RewindFastforwardType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof StopMoveType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof PlayPauseType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else if (command instanceof StringListType) {
value = command.toString();
} else if (command instanceof StringType) {
value = command.toString();
} else if (command instanceof UpDownType) { // Need to surround with double quotes
value = command.toString().toLowerCase();
} else {
logger.warn(
"Warning - The Smartthings converter does not know how to handle the {} command. The Smartthingsonverter class should be updated. CapabilityKey: {}, capabilityAttribute {}",
command.getClass().getName(), thingTypeId, channelUid.getId());
value = command.toString().toLowerCase();
}
public abstract State convertToOpenHabInternal(Thing thing, ChannelUID channelUid, Object dataFromSmartthings);

String jsonMsg = "";
private SmartthingsActions smartthingsActions = new SmartthingsActions();

Channel channel = thing.getChannel(channelUid);
Map<String, String> properties = channel.getProperties();
String componentKey = properties.get("component");
String capaKey = properties.get("capability");
String attrKey = properties.get("attribute");
private class SmartthingsActions {
Queue<SmartthingsAction> commands = new LinkedList<SmartthingsAction>();

SmartthingsCapabilitie capa = null;
SmartthingsAttribute attr = null;
if (capaKey != null) {
capa = typeRegistry.getCapabilities(capaKey);
}
if (attrKey != null) {
attr = capa.attributes.get(attrKey);
}

Boolean extendedFormat = false;
String cmdName = "";
String arguments = "[ ";

if (capa != null && attr != null) {
if (attrKey.equals("color")) {
attr.setter = "setColor";
}

if (attr.setter != null) {
SmartthingsCommand cmd = capa.commands.get(attr.setter);
cmdName = cmd.name;
int i = 0;
for (SmartthingsArgument arg : cmd.arguments) {
if (arg.optional) {
continue;
}
if (i > 0) {
arguments = arguments + " ,";
}
arguments += value;
i++;
}
arguments = arguments + "]";
extendedFormat = true;
}
public void pushCommand(@Nullable String component, @Nullable String capability, @Nullable String cmdName,
Object @Nullable [] arguments) {
commands.add(new SmartthingsAction(component, capability, cmdName, arguments));
}
}

if (extendedFormat) {
jsonMsg = String.format(
"{'commands': [{'component': '%s', 'capability': '%s', 'command': '%s', 'arguments': %s }]}",
componentKey, capaKey, cmdName, arguments);
} else {
jsonMsg = String.format("{'commands': [{'component': '%s', 'capability': '%s', 'command': '%s'}]}",
componentKey, capaKey, value);
private class SmartthingsAction {
@Nullable
public String component;
@Nullable
public String capability;
@Nullable
public String command;
@Nullable
public Object @Nullable [] arguments;

public SmartthingsAction(@Nullable String component, @Nullable String capability, @Nullable String command,
Object @Nullable [] arguments) {
this.component = component;
this.capability = capability;
this.command = command;
this.arguments = arguments;
}
}

// switchLevel
// setLevel
// jsonMsg = String.format(
// "{\"capabilityKey\": \"%s\", \"deviceDisplayName\": \"%s\", \"capabilityAttribute\": \"%s\", \"value\": %s}",
// thingTypeId, smartthingsName, channelUid.getId(), value);
public void pushCommand(@Nullable String component, @Nullable String capability, @Nullable String command,
Object @Nullable [] arguments) {
smartthingsActions.pushCommand(component, capability, command, arguments);
}

// "{'commands': [{'component': '%s', 'capability': '%s', 'command': 'setLevel', 'arguments': [%s, 2]}]}",
// jsonMsg = String.format("{'commands': [{'component': 'main', 'capability': 'switch', 'command': '%s'}]}",
// value);
private String getJSonCommands() {

return jsonMsg;
String result = gson.toJson(smartthingsActions);
smartthingsActions.commands.clear();
return result;
}

protected String surroundWithQuotes(String param) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.smartthings.internal.converter;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.smartthings.internal.type.SmartthingsTypeRegistry;

/**
* A factory for creating converters based on the itemType.
*
* @author Laurent Arnal - Initial contribution
*/

@NonNullByDefault
public class SmartthingsConverterFactory {
private static Map<String, SmartthingsConverter> converterCache = new HashMap<>();

public static void registerConverters(SmartthingsTypeRegistry typeRegistry) {
registerConverter("color", new SmartthingsColorConverter(typeRegistry));
registerConverter("default", new SmartthingsDefaultConverter(typeRegistry));
}

private static void registerConverter(String key, SmartthingsConverter tp) {
converterCache.put(key, tp);
}

/**
* Returns the converter for an itemType.
*/
public static @Nullable SmartthingsConverter getConverter(String itemType) {
SmartthingsConverter converter = converterCache.get(itemType);
return converter;
}
}
Loading

0 comments on commit 29e6fd7

Please sign in to comment.