added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.folding-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-folding" description="Folding Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.folding/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link FoldingBinding} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Marius Bjoernstad - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoldingBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "folding";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_CLIENT = new ThingTypeUID(BINDING_ID, "client");
|
||||
public static final ThingTypeUID THING_TYPE_SLOT = new ThingTypeUID(BINDING_ID, "slot");
|
||||
|
||||
public static final String PARAM_SLOT_ID = "id";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_STATUS = "status";
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.folding.internal.handler.FoldingClientHandler;
|
||||
import org.openhab.binding.folding.internal.handler.SlotHandler;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link FoldingHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Marius Bjoernstad - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.folding")
|
||||
public class FoldingHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = new HashSet<>(
|
||||
Arrays.asList(FoldingBindingConstants.THING_TYPE_CLIENT, FoldingBindingConstants.THING_TYPE_SLOT));
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(FoldingBindingConstants.THING_TYPE_CLIENT)) {
|
||||
return new FoldingClientHandler((Bridge) thing);
|
||||
} else if (thingTypeUID.equals(FoldingBindingConstants.THING_TYPE_SLOT)) {
|
||||
return new SlotHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.discovery;
|
||||
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* Singleton instance to connect the Client handler and the discovery
|
||||
* service.
|
||||
*
|
||||
* @author Marius Bjoernstad - Initial contribution
|
||||
*/
|
||||
public class FoldingDiscoveryProxy {
|
||||
|
||||
private static FoldingDiscoveryProxy instance;
|
||||
private FoldingSlotDiscoveryService discoveryService = null;
|
||||
|
||||
private FoldingDiscoveryProxy() {
|
||||
}
|
||||
|
||||
public static FoldingDiscoveryProxy getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new FoldingDiscoveryProxy();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void setService(FoldingSlotDiscoveryService service) {
|
||||
this.discoveryService = service;
|
||||
}
|
||||
|
||||
public void newSlot(ThingUID bridgeUID, String host, String id, String description) {
|
||||
if (instance != null) {
|
||||
discoveryService.newSlot(bridgeUID, host, id, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.discovery;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.folding.internal.FoldingBindingConstants;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* Discovery service implementation.
|
||||
*
|
||||
* The Client handler has to be configured manually, but once connected,
|
||||
* it will publish discovered slots to this service. This service converts
|
||||
* the internal representation to discovery results.
|
||||
*
|
||||
* @author Marius Bjoernstad - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.folding")
|
||||
public class FoldingSlotDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
public FoldingSlotDiscoveryService() {
|
||||
super(Collections.singleton(FoldingBindingConstants.THING_TYPE_SLOT), 10, true);
|
||||
FoldingDiscoveryProxy.getInstance().setService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
}
|
||||
|
||||
protected String getLabel(String host, String description) {
|
||||
if (description == null) {
|
||||
description = "slot";
|
||||
}
|
||||
int endOfLabel = description.indexOf(' ');
|
||||
if (endOfLabel > 0) {
|
||||
description = description.substring(0, endOfLabel);
|
||||
}
|
||||
endOfLabel = description.indexOf(':');
|
||||
if (endOfLabel > 0) {
|
||||
description = description.substring(0, endOfLabel);
|
||||
}
|
||||
return description + " @ " + host;
|
||||
}
|
||||
|
||||
public void newSlot(ThingUID bridgeUID, String host, String id, String description) {
|
||||
if (isBackgroundDiscoveryEnabled() && id != null) {
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
properties.put(FoldingBindingConstants.PARAM_SLOT_ID, id);
|
||||
ThingUID thingUID = new ThingUID(FoldingBindingConstants.THING_TYPE_SLOT, bridgeUID, id);
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridgeUID).withLabel(getLabel(host, description)).build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.handler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.folding.internal.discovery.FoldingDiscoveryProxy;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
/**
|
||||
* The {@link FoldingClientHandler} connects to a single Folding@home client,
|
||||
* and controls it. The Client handler can also act as a bridge for the
|
||||
* {@link SlotHandler}.
|
||||
*
|
||||
* @author Marius Bjørnstad - Initial contribution
|
||||
*/
|
||||
public class FoldingClientHandler extends BaseBridgeHandler {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(FoldingClientHandler.class);
|
||||
|
||||
private ScheduledFuture<?> refreshJob;
|
||||
|
||||
private boolean initializing = true;
|
||||
|
||||
private Socket activeSocket;
|
||||
private BufferedReader socketReader;
|
||||
private Gson gson;
|
||||
|
||||
private volatile int idRefresh = 0;
|
||||
|
||||
private Map<String, SlotUpdateListener> slotUpdateListeners = new HashMap<>();
|
||||
|
||||
public FoldingClientHandler(Bridge thing) {
|
||||
super(thing);
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
try {
|
||||
if (command instanceof RefreshType) {
|
||||
refresh();
|
||||
} else if (channelUID.getId().equals("run")) {
|
||||
if (command == OnOffType.ON) {
|
||||
sendCommand("unpause");
|
||||
} else if (command == OnOffType.OFF) {
|
||||
sendCommand("pause");
|
||||
}
|
||||
refresh();
|
||||
delayedRefresh();
|
||||
} else if (channelUID.getId().equals("finish")) {
|
||||
if (command == OnOffType.ON) {
|
||||
sendCommand("finish");
|
||||
} else if (command == OnOffType.OFF) {
|
||||
sendCommand("unpause");
|
||||
}
|
||||
refresh();
|
||||
delayedRefresh();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("Input/output error while handing command", e);
|
||||
disconnected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
BigDecimal period = (BigDecimal) getThing().getConfiguration().get("polling");
|
||||
if (period != null && period.longValue() != 0) {
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 5, period.longValue(), TimeUnit.SECONDS);
|
||||
} else {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void dispose() {
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
}
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
public synchronized void refresh() {
|
||||
initializing = false;
|
||||
List<SlotInfo> slotList = null;
|
||||
try {
|
||||
Socket s = getSocket();
|
||||
s.getOutputStream().write(("slot-info\r\n").getBytes());
|
||||
socketReader.readLine(); // Discard PyON header
|
||||
JsonReader jr = new JsonReader(socketReader);
|
||||
jr.setLenient(true);
|
||||
Type slotListType = new TypeToken<List<SlotInfo>>() {
|
||||
}.getType();
|
||||
|
||||
slotList = gson.fromJson(jr, slotListType);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Input/error while refreshing Folding client state", e);
|
||||
disconnected();
|
||||
return;
|
||||
}
|
||||
boolean running = false, finishing = true;
|
||||
for (SlotInfo si : slotList) {
|
||||
finishing &= "FINISHING".equals(si.status);
|
||||
running |= "FINISHING".equals(si.status) || "RUNNING".equals(si.status);
|
||||
SlotUpdateListener listener = slotUpdateListeners.get(si.id);
|
||||
if (listener != null) {
|
||||
listener.refreshed(si);
|
||||
} else {
|
||||
logger.debug("Providing a new discovery result for slot {}", si.id);
|
||||
String host = (String) getThing().getConfiguration().get("host");
|
||||
FoldingDiscoveryProxy.getInstance().newSlot(getThing().getUID(), host, si.id, si.description);
|
||||
}
|
||||
}
|
||||
updateState(getThing().getChannel("run").getUID(), running ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(getThing().getChannel("finish").getUID(), finishing ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
public void delayedRefresh() {
|
||||
final int iRefresh = ++idRefresh;
|
||||
refreshJob = scheduler.schedule(() -> {
|
||||
if (iRefresh == idRefresh) { // Make a best effort to not run multiple deferred refresh
|
||||
refresh();
|
||||
}
|
||||
}, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
void closeSocket() {
|
||||
if (activeSocket != null && activeSocket.isConnected()) {
|
||||
try {
|
||||
socketReader.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
socketReader = null;
|
||||
activeSocket = null;
|
||||
}
|
||||
|
||||
private void disconnected() {
|
||||
closeSocket();
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
|
||||
private synchronized Socket getSocket() throws IOException {
|
||||
if (activeSocket == null) {
|
||||
String cfgHost = (String) getThing().getConfiguration().get("host");
|
||||
BigDecimal cfgPort = (BigDecimal) getThing().getConfiguration().get("port");
|
||||
String password = (String) getThing().getConfiguration().get("password");
|
||||
if (cfgHost == null || cfgHost.isEmpty()) {
|
||||
throw new IOException("Host was not configured");
|
||||
} else if (cfgPort == null || cfgPort.intValue() == 0) {
|
||||
throw new IOException("Port was not configured");
|
||||
}
|
||||
activeSocket = new Socket();
|
||||
activeSocket.connect(new InetSocketAddress(cfgHost, cfgPort.intValue()), 2000);
|
||||
socketReader = new BufferedReader(new InputStreamReader(activeSocket.getInputStream()));
|
||||
readUntilPrompt(activeSocket); // Discard initial banner message
|
||||
if (password != null) {
|
||||
activeSocket.getOutputStream().write(("auth \"" + password + "\"\r\n").getBytes());
|
||||
if (readUntilPrompt(activeSocket).startsWith("OK")) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect password");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
return activeSocket;
|
||||
}
|
||||
|
||||
private synchronized String readUntilPrompt(Socket s) throws IOException {
|
||||
boolean havePrompt1 = false;
|
||||
StringBuilder response = new StringBuilder();
|
||||
try {
|
||||
while (true) {
|
||||
int c = socketReader.read();
|
||||
if (havePrompt1) {
|
||||
if (c == ' ') {
|
||||
return response.toString();
|
||||
} else {
|
||||
response.append((char) c);
|
||||
}
|
||||
}
|
||||
response.append((char) c);
|
||||
havePrompt1 = (c == '>');
|
||||
}
|
||||
} catch (IOException e) {
|
||||
disconnected();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendCommand(String command) throws IOException {
|
||||
try {
|
||||
Socket s = getSocket();
|
||||
s.getOutputStream().write((command + "\r\n").getBytes());
|
||||
readUntilPrompt(s);
|
||||
} catch (IOException e) {
|
||||
disconnected();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerSlot(String id, SlotUpdateListener slotListener) {
|
||||
slotUpdateListeners.put(id, slotListener);
|
||||
if (!initializing) {
|
||||
delayedRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Thing handler representing a Folding slot.
|
||||
*
|
||||
* If control of each slot (CPU, GPUs, etc.) is desired, the user can add
|
||||
* Slot handlers. The Slot handler exposes the status of a slot, and allows
|
||||
* users to start / stop folding.
|
||||
*
|
||||
* @author Marius Bjørnstad - Initial contribution
|
||||
*/
|
||||
public class SlotHandler extends BaseThingHandler implements SlotUpdateListener {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(SlotHandler.class);
|
||||
|
||||
public SlotHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
getBridgeHandler().registerSlot(myId(), this);
|
||||
}
|
||||
|
||||
private FoldingClientHandler getBridgeHandler() {
|
||||
return (FoldingClientHandler) super.getBridge().getHandler();
|
||||
}
|
||||
|
||||
private String myId() {
|
||||
return (String) getThing().getConfiguration().get("id");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
try {
|
||||
if (channelUID.getId().equals("run")) {
|
||||
if (command == OnOffType.ON) {
|
||||
getBridgeHandler().sendCommand("unpause " + myId());
|
||||
} else if (command == OnOffType.OFF) {
|
||||
getBridgeHandler().sendCommand("pause " + myId());
|
||||
}
|
||||
} else if (channelUID.getId().equals("finish")) {
|
||||
if (command == OnOffType.ON) {
|
||||
getBridgeHandler().sendCommand("finish " + myId());
|
||||
} else if (command == OnOffType.OFF) {
|
||||
getBridgeHandler().sendCommand("unpause " + myId());
|
||||
}
|
||||
}
|
||||
getBridgeHandler().refresh();
|
||||
getBridgeHandler().delayedRefresh();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Input/output error while handing command to Folding slot", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshed(SlotInfo si) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateState(getThing().getChannel("status").getUID(), new StringType(si.status));
|
||||
boolean finishing = "FINISHING".equals(si.status);
|
||||
boolean run = finishing || "READY".equals(si.status) || "RUNNING".equals(si.status);
|
||||
updateState(getThing().getChannel("finish").getUID(), finishing ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(getThing().getChannel("run").getUID(), run ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(getThing().getChannel("description").getUID(), new StringType(si.description));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Slot information entity
|
||||
*
|
||||
* This class specifies the format of the Json-compatible data received from
|
||||
* the Folding client process.
|
||||
*
|
||||
* @author Marius Bjoernstad - Initial contribution
|
||||
*/
|
||||
public class SlotInfo {
|
||||
|
||||
public String id, status, description, reason;
|
||||
public Map<String, String> options;
|
||||
boolean idle;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.folding.internal.handler;
|
||||
|
||||
/**
|
||||
* Interface for callback from Client handler to Slot handler.
|
||||
*
|
||||
* The client performs refreshes regularly, retrieving information about
|
||||
* all slots. It then calls refreshed on all registered SlotUpdateListeners.
|
||||
*
|
||||
* @author Marius Bjørnstad - Initial contribution
|
||||
*/
|
||||
public interface SlotUpdateListener {
|
||||
void refreshed(SlotInfo si);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="folding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Folding@home</name>
|
||||
<description>Control Folding@home clients on computers.</description>
|
||||
<author>Marius Bjoernstad</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="folding"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="client">
|
||||
<label>Client</label>
|
||||
<description>Folding@home client daemon (represented as bridge).</description>
|
||||
|
||||
<channels>
|
||||
<channel id="run" typeId="run"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="host" type="text">
|
||||
<label>Host</label>
|
||||
<description>Hostname or IP address</description>
|
||||
<default>127.0.0.1</default>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer">
|
||||
<label>Port</label>
|
||||
<description></description>
|
||||
<default>36330</default>
|
||||
</parameter>
|
||||
<parameter name="password" type="text">
|
||||
<label>Password</label>
|
||||
<description>Authentication password (leave empty for no p/w).</description>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
<parameter name="polling" type="integer" unit="s">
|
||||
<label>Polling Interval</label>
|
||||
<description>Polling interval in seconds (0=polling disabled).</description>
|
||||
<default>120</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
<channel-type id="run">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Run</label>
|
||||
<description>Slot running.</description>
|
||||
</channel-type>
|
||||
<channel-type id="finish">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Finish</label>
|
||||
<description>Finish current work then pause.</description>
|
||||
</channel-type>
|
||||
|
||||
<thing-type id="slot">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="client"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Slot</label>
|
||||
<description>Folding client compute slot.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="description" typeId="description"/>
|
||||
<channel id="run" typeId="run"/>
|
||||
<channel id="finish" typeId="finish"/>
|
||||
<channel id="status" typeId="status"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="id" type="text">
|
||||
<label>Slot ID</label>
|
||||
<description>Slot ID, "00", "01", etc.</description>
|
||||
<default>00</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="description">
|
||||
<item-type>String</item-type>
|
||||
<label>Description</label>
|
||||
<description>Description of the Folding@home slot.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
<channel-type id="status">
|
||||
<item-type>String</item-type>
|
||||
<label>Status</label>
|
||||
<description>Current status</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user