added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.folding</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-addons

View File

@@ -0,0 +1,33 @@
# Folding@home Binding
Binding for the [Folding@home](https://folding.stanford.edu/) distributed computing
software.
This binding can control multiple Folding@home clients and slots, using the TCP
interface.
Clients are modeled as bridges, and support adding any number of slots
(though, usually CPU and GPU).
The binding provides control over Run / Pause and Finish.
It polls for the status of the client, updates the run / pause state, and
provides a basic description of the slot.
The clients must be added manually in the Paper UI, but the slots for that
client will then appear using auto-discovery.
## Requirements (network access to F@H)
The Folding@home TCP interface is enabled only on localhost by default, without
a password.
In order to allow control of Folding on other machines than the one
running openHAB, it is necessary to configure the Folding client to accept commands
from a non-localhost address.
Here is how to do it in the FAHControl application:
- Open FAHControl on the client to be added
- Click on Configure, then the Remote Access tab
- Enter a password twice (invent one)
- Locate the Allow box under IP Address Restrictions
- Append a space and the IP address of the machine running openHAB to the text in that box, so it reads something like `127.0.0.1 192.168.1.2`
You should now have access to the client, configure it using the password and
IP address in the manual thing configuration interface.

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.folding</artifactId>
<name>openHAB Add-ons :: Bundles :: Folding Binding</name>
</project>

View File

@@ -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>

View File

@@ -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";
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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>