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,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.seneye-${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-seneye" description="Seneye Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.seneye/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,32 @@
/**
* 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.seneye.internal;
/**
* There was an error while communicating with the seneye API.
* This will be mostly temporary communication errors.
*
* @author Niko Tanghe - Initial contribution
*/
public class CommunicationException extends Exception {
private static final long serialVersionUID = -1397248504578142737L;
public CommunicationException(String message) {
super(message);
}
public CommunicationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,27 @@
/**
* 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.seneye.internal;
/**
* There was an error in the seneye configuration
*
* @author Niko Tanghe - Initial contribution
*/
public class InvalidConfigurationException extends Exception {
private static final long serialVersionUID = -2894268584378662737L;
public InvalidConfigurationException(String message) {
super(message);
}
}

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.seneye.internal;
/**
* Interface for readings updates
*
* @author Niko Tanghe - Initial contribution
*/
public interface ReadingsUpdate {
public void newState(SeneyeDeviceReading devicereadings);
public void invalidConfig();
}

View File

@@ -0,0 +1,26 @@
/**
* 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.seneye.internal;
/**
* Identification of a seneye device
*
* @author Niko Tanghe - Initial contribution
*/
public class Seneye {
public int id;
public String description;
public int type;
public int time_diff;
}

View File

@@ -0,0 +1,57 @@
/**
* 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.seneye.internal;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link SeneyeBinding} class defines common constants, which are
* used across the whole binding.
*
* @author Niko Tanghe - Initial contribution
*/
@NonNullByDefault
public class SeneyeBindingConstants {
public static final String BINDING_ID = "seneye";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_SENEYE = new ThingTypeUID(BINDING_ID, "monitor");
// List of all Channel ids
public static final String CHANNEL_TEMPERATURE = "temperature";
public static final String CHANNEL_PH = "ph";
public static final String CHANNEL_NH3 = "nh3";
public static final String CHANNEL_NH4 = "nh4";
public static final String CHANNEL_O2 = "O2";
public static final String CHANNEL_LUX = "lux";
public static final String CHANNEL_PAR = "par";
public static final String CHANNEL_KELVIN = "kelvin";
public static final String CHANNEL_LASTREADING = "lastreading";
public static final String CHANNEL_SLIDEEXPIRES = "slideexpires";
public static final String CHANNEL_WRONGSLIDE = "wrongslide";
public static final String CHANNEL_SLIDESERIAL = "slideserial";
public static final String CHANNEL_OUTOFWATER = "outofwater";
public static final String CHANNEL_DISCONNECTED = "disconnected";
// List of all Parameters
public static final String PARAMETER_AQUARIUMNAME = "aquariumname";
public static final String PARAMETER_USERNAME = "username";
public static final String PARAMETER_PASSWORD = "password";
public static final String PARAMETER_POLLTIME = "polltime";
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_SENEYE);
}

View File

@@ -0,0 +1,32 @@
/**
* 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.seneye.internal;
/**
* Contains the configuration parameters for the smappee device.
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeConfigurationParameters {
/** The name of your aquarium. */
public String aquarium_name;
/** The username for My Seneye. */
public String username;
/** The password for My Seneye. */
public String password;
/** How often (in minutes) does the seneye needs to be checked ? */
public int poll_time;
}

View File

@@ -0,0 +1,31 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReading {
public SeneyeStatus status;
public SeneyeDeviceReadingTemperature temperature;
public SeneyeDeviceReadingPh ph;
public SeneyeDeviceReadingNh3 nh3;
public SeneyeDeviceReadingNh4 nh4;
public SeneyeDeviceReadingO2 o2;
public SeneyeDeviceReadingLux lux;
public SeneyeDeviceReadingPar par;
public SeneyeDeviceReadingKelvin kelvin;
}

View File

@@ -0,0 +1,24 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - advice which action to take
* Now empty because not sure what this should contain
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingAdvice {
}

View File

@@ -0,0 +1,24 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - Light intensity in Kelvin
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingKelvin {
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,24 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - Light intensity in Lux
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingLux {
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,28 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - The NH3 water level
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingNh3 {
public int trend;
public int critical_in;
public double avg;
public boolean status;
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,28 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - The NH4 water level
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingNh4 {
public int trend;
public int critical_in;
public double avg;
public boolean status;
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,28 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - The O2 water level
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingO2 {
public int trend;
public int critical_in;
public double avg;
public boolean status;
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,24 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - Light intensity in Par
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingPar {
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,28 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - The PH water level
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingPh {
public int trend;
public int critical_in;
public double avg;
public boolean status;
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,28 @@
/**
* 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.seneye.internal;
/**
* The result of a seneye readout - The water Temperature level
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeDeviceReadingTemperature {
public int trend;
public int critical_in;
public double avg;
public boolean status;
public double curr;
public SeneyeDeviceReadingAdvice[] advices;
}

View File

@@ -0,0 +1,54 @@
/**
* 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.seneye.internal;
import static org.openhab.binding.seneye.internal.SeneyeBindingConstants.THING_TYPE_SENEYE;
import java.util.Collections;
import java.util.Set;
import org.openhab.binding.seneye.internal.handler.SeneyeHandler;
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 SeneyeHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Niko Tanghe - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.seneye")
public class SeneyeHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_SENEYE);
@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(THING_TYPE_SENEYE)) {
return new SeneyeHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,172 @@
/**
* 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.seneye.internal;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* The {@link SeneyeService} handles the connection to the Seneye API
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeService {
private final Logger logger = LoggerFactory.getLogger(SeneyeService.class);
private int retry;
private SeneyeConfigurationParameters config;
private String seneyeId;
public int seneyeType;
private boolean isInitialized;
private final Gson gson;
private HttpClient httpClient = new HttpClient(new SslContextFactory());
private ScheduledFuture<?> scheduledJob;
public SeneyeService(SeneyeConfigurationParameters config) throws CommunicationException {
this.config = config;
this.retry = 1;
this.gson = new Gson();
this.isInitialized = false;
if (!httpClient.isStarted()) {
try {
httpClient.setFollowRedirects(false);
httpClient.start();
} catch (Exception e) {
throw new CommunicationException("Cannot start HttpClient!", e);
}
}
}
@Override
public void finalize() {
try {
httpClient.stop();
} catch (Exception e) {
// swallow this
}
httpClient = null;
}
public void startAutomaticRefresh(ScheduledExecutorService scheduledExecutorService,
final ReadingsUpdate readingsUpdate) {
scheduledJob = scheduledExecutorService.scheduleWithFixedDelay(() -> {
readingsUpdate.newState(getDeviceReadings());
}, 0, config.poll_time, TimeUnit.MINUTES);
}
public void stopAutomaticRefresh() {
if (scheduledJob != null) {
scheduledJob.cancel(true);
}
}
public SeneyeDeviceReading getDeviceReadings() {
int currentTry = 0;
do {
try {
String responseState = getData("/" + seneyeId + "/state?" + getCredentials());
String responseReadings = getData("/" + seneyeId + "/exps?" + getCredentials());
SeneyeDeviceReading readings = gson.fromJson(responseReadings, SeneyeDeviceReading.class);
readings.status = gson.fromJson(responseState, SeneyeStatus.class);
logger.debug("seneye '{}' read", this.seneyeId);
return readings;
} catch (Exception se) {
// ok, this readout failed, swallow this error, this is a scheduled task and this is in a retry loop,
// so it will be retried.
logger.debug("failed to read seneye '{}'", se.getMessage());
}
} while (currentTry++ < this.retry);
return null;
}
public void initialize() throws CommunicationException, InvalidConfigurationException {
String response = getData("?" + getCredentials());
Seneye[] seneyeDevices = gson.fromJson(response, Seneye[].class);
for (Seneye seneye : seneyeDevices) {
if (seneye.description.equals(config.aquarium_name)) {
seneyeId = Integer.toString(seneye.id);
seneyeType = (seneye.type);
isInitialized = true;
return;
}
}
throw new InvalidConfigurationException(
"Could not find a seneye with aquarium name '" + config.aquarium_name + "'");
}
public boolean isInitialized() {
return isInitialized;
}
private String getData(String request) throws CommunicationException {
// get devices
// https://api.seneye.com/v1/devices?user=emailaddress&pwd=xxx
// get devicestatus
// https://api.seneye.com/v1/devices/23142/state?user=emailaddress&pwd=xxx
// get readings
// https://api.seneye.com/v1/devices/23142/exps?user=emailaddress&pwd=xxx
// get advices
// https://api.seneye.com/v1/devices/23142/advices/<id>?user=emailaddress&pwd=xxx
String url = "https://api.seneye.com/v1/devices" + request;
Request getMethod = httpClient.newRequest(url);
getMethod.accept("application/json");
try {
ContentResponse response = getMethod.send();
if (response.getStatus() != HttpStatus.OK_200) {
logger.debug("Get readings method failed: {}", response.getReason());
return "";
}
return response.getContentAsString();
} catch (InterruptedException e) {
throw new CommunicationException("Request aborted", e);
} catch (TimeoutException e) {
throw new CommunicationException("Timeout error", e);
} catch (ExecutionException e) {
throw new CommunicationException("Communication error", e.getCause());
}
}
private String getCredentials() {
return "user=" + config.username + "&pwd=" + config.password;
}
}

View File

@@ -0,0 +1,60 @@
/**
* 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.seneye.internal;
import org.openhab.core.library.types.DateTimeType;
/**
* The Status of the seneye device
*
* @author Niko Tanghe - Initial contribution
*/
public class SeneyeStatus {
public String disconnected;
public String slide_serial;
public String slide_expires;
public String out_of_water;
public String wrong_slide;
public String last_experiment;
public String getLast_experimentDate() {
return getTickAsDate(last_experiment);
}
public String getSlide_expiresDate() {
return getTickAsDate(slide_expires);
}
private String getTickAsDate(String tick) {
String date = new java.text.SimpleDateFormat(DateTimeType.DATE_PATTERN_WITH_TZ_AND_MS_ISO)
.format(new java.util.Date(Long.parseLong(tick) * 1000));
return date;
}
public String getWrong_slideString() {
return wrong_slide;
}
public String getSlide_serialString() {
return slide_serial;
}
public String getOut_of_waterString() {
return out_of_water;
}
public String getDisconnectedString() {
return disconnected;
}
}

View File

@@ -0,0 +1,168 @@
/**
* 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.seneye.internal.handler;
import static org.openhab.binding.seneye.internal.SeneyeBindingConstants.*;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.seneye.internal.CommunicationException;
import org.openhab.binding.seneye.internal.InvalidConfigurationException;
import org.openhab.binding.seneye.internal.ReadingsUpdate;
import org.openhab.binding.seneye.internal.SeneyeConfigurationParameters;
import org.openhab.binding.seneye.internal.SeneyeDeviceReading;
import org.openhab.binding.seneye.internal.SeneyeService;
import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
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.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link SeneyeHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Niko Tanghe - Initial contribution
*/
public final class SeneyeHandler extends BaseThingHandler implements ReadingsUpdate {
private final Logger logger = LoggerFactory.getLogger(SeneyeHandler.class);
private SeneyeService seneyeService;
private ExpiringCache<SeneyeDeviceReading> cachedSeneyeDeviceReading;
public SeneyeHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (seneyeService == null || !seneyeService.isInitialized()) {
return;
}
if (command instanceof RefreshType) {
SeneyeDeviceReading readings = cachedSeneyeDeviceReading.getValue();
newState(readings);
} else {
logger.debug("Command {} is not supported for channel: {}", command, channelUID.getId());
}
}
@Override
public void newState(SeneyeDeviceReading readings) {
if (readings != null) {
logger.debug("Updating readings for sensor type {}", seneyeService.seneyeType);
switch (seneyeService.seneyeType) {
case 3:
updateState(CHANNEL_NH4, new DecimalType(readings.nh4.curr));
updateState(CHANNEL_PAR, new DecimalType(readings.par.curr));
updateState(CHANNEL_LUX, new DecimalType(readings.lux.curr));
updateState(CHANNEL_KELVIN, new DecimalType(readings.kelvin.curr));
case 2:
updateState(CHANNEL_O2, new DecimalType(readings.o2.curr));
case 1:
updateState(CHANNEL_TEMPERATURE, new DecimalType(readings.temperature.curr));
updateState(CHANNEL_NH3, new DecimalType(readings.nh3.curr));
updateState(CHANNEL_PH, new DecimalType(readings.ph.curr));
updateState(CHANNEL_LASTREADING, new DateTimeType(readings.status.getLast_experimentDate()));
updateState(CHANNEL_SLIDEEXPIRES, new DateTimeType(readings.status.getSlide_expiresDate()));
updateState(CHANNEL_WRONGSLIDE, new StringType(readings.status.getWrong_slideString()));
updateState(CHANNEL_SLIDESERIAL, new StringType(readings.status.getSlide_serialString()));
updateState(CHANNEL_OUTOFWATER, new StringType(readings.status.getOut_of_waterString()));
updateState(CHANNEL_DISCONNECTED, new StringType(readings.status.getDisconnectedString()));
}
}
}
@Override
public void invalidConfig() {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
}
@Override
public void initialize() {
SeneyeConfigurationParameters config = getConfigAs(SeneyeConfigurationParameters.class);
if (config.aquarium_name == null || config.aquarium_name.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Check configuration, Aquarium name must be provided");
return;
}
if (config.username == null || config.username.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Check configuration, Seneye username must be provided");
return;
}
if (config.password == null || config.password.isEmpty()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Check configuration, Seneye password must be provided");
return;
}
logger.debug("Initializing Seneye API service.");
try {
this.seneyeService = new SeneyeService(config);
} catch (CommunicationException ex) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ex.getMessage());
return; // critical error
}
super.initialize();
// contact Seneye API
scheduler.submit(() -> {
initializeSeneyeService();
});
}
private void initializeSeneyeService() {
try {
seneyeService.initialize();
} catch (CommunicationException ex) {
// try again in 30 secs
scheduler.schedule(() -> {
initializeSeneyeService();
}, 30, TimeUnit.SECONDS);
return;
} catch (InvalidConfigurationException ex) {
// bad configuration, stay offline until user corrects the configuration
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, ex.getMessage());
return;
}
// ok, initialization succeeded
cachedSeneyeDeviceReading = new ExpiringCache<>(TimeUnit.SECONDS.toMillis(10), () -> {
return seneyeService.getDeviceReadings();
});
seneyeService.startAutomaticRefresh(scheduler, this);
updateStatus(ThingStatus.ONLINE);
}
@Override
public void dispose() {
seneyeService.stopAutomaticRefresh();
seneyeService = null;
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="seneye" 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>Seneye Binding</name>
<description>The seneye binding polls the seneye API for your aquarium readings.</description>
<author>Niko Tanghe</author>
</binding:binding>

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="seneye"
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">
<thing-type id="monitor">
<label>Seneye Monitor</label>
<description>Seneye Monitor</description>
<channels>
<channel id="temperature" typeId="temperature"/>
<channel id="ph" typeId="ph"/>
<channel id="nh3" typeId="nh3"/>
<channel id="nh4" typeId="nh4"/>
<channel id="O2" typeId="o2"/>
<channel id="lux" typeId="lux"/>
<channel id="par" typeId="par"/>
<channel id="kelvin" typeId="kelvin"/>
<channel id="lastreading" typeId="lastreading"/>
<channel id="slideexpires" typeId="slideexpires"/>
<channel id="wrongslide" typeId="wrongslide"/>
<channel id="slideserial" typeId="slideserial"/>
<channel id="outofwater" typeId="outofwater"/>
<channel id="disconnected" typeId="disconnected"/>
</channels>
<config-description>
<parameter name="aquarium_name" type="text" required="true">
<label>Aquarium Name</label>
<description>The name of your aquarium</description>
</parameter>
<parameter name="username" type="text" required="true">
<label>Username</label>
<description>The email address used to login to My Seneye</description>
</parameter>
<parameter name="password" type="text" required="true">
<label>Password</label>
<description>The password of My Seneye</description>
<context>password</context>
</parameter>
<parameter name="poll_time" type="integer" required="false" min="1" max="1440">
<label>Polling Time</label>
<description>How often (in minutes) does the seneye needs to be checked ?</description>
<default>5</default>
</parameter>
</config-description>
</thing-type>
<!-- Channels -->
<channel-type id="temperature">
<item-type>Number</item-type>
<label>Temperature</label>
<description>The water temperature</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="ph">
<item-type>Number</item-type>
<label>PH</label>
<description>The PH Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="nh3">
<item-type>Number</item-type>
<label>NH3</label>
<description>The NH3 Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="nh4">
<item-type>Number</item-type>
<label>NH4</label>
<description>The NH4 Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="o2">
<item-type>Number</item-type>
<label>O2</label>
<description>The O2 Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="lux">
<item-type>Number</item-type>
<label>LUX</label>
<description>The LUX Light Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="par">
<item-type>Number</item-type>
<label>PAR</label>
<description>The PAR Light Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="kelvin">
<item-type>Number</item-type>
<label>Kelvin</label>
<description>The Kelvin Light Level</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="lastreading">
<item-type>DateTime</item-type>
<label>Last Reading</label>
<description>The last time your seneye is checked</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="slideexpires">
<item-type>DateTime</item-type>
<label>Slide Expiration</label>
<description>The time your slide expires</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="wrongslide">
<item-type>String</item-type>
<label>Wrong Slide</label>
<description>The Wrong Slide is in use (becomes 1 when the slide has expired)</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="slideserial">
<item-type>String</item-type>
<label>Slide Serial Number</label>
<description>The serial Number of the currently installed slide</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="outofwater">
<item-type>String</item-type>
<label>Out of Water</label>
<description>The Sensor is reporting being out of the water</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="disconnected">
<item-type>String</item-type>
<label>Disconnected</label>
<description>No readings have been uploaded for a while, check connection</description>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>