/**
* Copyright (c) 2010-2016 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.hms.internal;
import java.util.Dictionary;
import org.openhab.binding.hms.HMSBindingProvider;
import org.openhab.binding.hms.internal.HMSGenericBindingProvider.HMSBindingConfig;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.items.Item;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.io.transport.cul.CULLifecycleListenerListenerRegisterer;
import org.openhab.io.transport.cul.CULLifecycleManager;
import org.openhab.io.transport.cul.CULListener;
import org.openhab.io.transport.cul.CULMode;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class makes use of a CUL device in SLOW_RF mode and handles messages received via this channel.
*
* @author Thomas Urmann
* @since 1.7.0
*/
public class HMSBinding extends AbstractBinding<HMSBindingProvider>implements ManagedService, CULListener {
private static final Logger logger = LoggerFactory.getLogger(HMSBinding.class);
private final CULLifecycleManager culHandlerLifecycle;
public HMSBinding() {
culHandlerLifecycle = new CULLifecycleManager(CULMode.SLOW_RF,
new CULLifecycleListenerListenerRegisterer(this));
}
@Override
public void activate() {
culHandlerLifecycle.open();
}
@Override
public void deactivate() {
logger.debug("Deactivating HMS binding");
culHandlerLifecycle.close();
}
@Override
public void dataReceived(String data) {
// It is possible that we see here messages of other protocols
if (data.startsWith("H")) {
handleHMSMessage(data);
}
}
/**
* Code <s1><s0><t1><t0><f0><t2><f2><f1>
*
* similar perl code is:
* $v[0] = int(substr($val, 5, 1) . substr($val, 2, 2))/10;
* $v[0] = -$v[0] if($status1 & 8);
* $v[1] = int(substr($val, 6, 2) . substr($val, 4, 1))/10;
* $v[2] = $batstr1;
* $val = "T: $v[0] H: $v[1] Bat: $v[2]";
*/
protected void handleHMSMessage(String data) {
if (data.startsWith("H")) {
String device = data.substring(1, 5);
String woHeader = data.substring(5, data.length() - 1);
String s1 = woHeader.substring(0, 1);
String batteryStatus = "ok";
boolean isEmpty = (s1.charAt(0) & 2) == 2;
boolean isReplaced = (s1.charAt(0) & 4) == 4;
if (isEmpty) {
batteryStatus = "empty";
} else if (isReplaced) {
batteryStatus = "replaced";
}
double temperature = Integer.parseInt(woHeader.substring(5, 6) + woHeader.substring(2, 4)) / 10.0;
boolean isNegative = (s1.charAt(0) & 8) == 8;
if (isNegative) {
temperature = -temperature;
}
double humidity = Integer.parseInt(woHeader.substring(6, 8) + woHeader.substring(4, 5)) / 10.0;
logger.info("device: {}, T: {},\tH: {}, Bat.: {}", device, (!isNegative ? " " : "") + temperature, humidity,
batteryStatus);
HMSBindingConfig temperatureConfig = findConfig(device, HMSBindingConfig.Datapoint.TEMPERATURE);
if (temperatureConfig != null) {
updateItem(temperatureConfig.item, temperature);
}
HMSBindingConfig humidityConfig = findConfig(device, HMSBindingConfig.Datapoint.HUMIDITY);
if (humidityConfig != null) {
updateItem(humidityConfig.item, humidity);
}
} else {
logger.warn("Received unparseable message: " + data);
}
}
private void updateItem(Item item, double value) {
DecimalType type = new DecimalType(value);
eventPublisher.postUpdate(item.getName(), type);
}
private HMSBindingConfig findConfig(String address, HMSBindingConfig.Datapoint datapoint) {
for (HMSBindingProvider provider : this.providers) {
HMSBindingConfig config = provider.getBindingConfigForAddressAndDatapoint(address, datapoint);
if (config != null) {
return config;
}
}
return null;
}
@Override
protected void internalReceiveCommand(String itemName, Command command) {
// the code being executed when a command was sent on the openHAB
// event bus goes here. This method is only called if one of the
// BindingProviders provide a binding for the given 'itemName'.
logger.debug("internalReceiveCommand() is called!");
}
@Override
protected void internalReceiveUpdate(String itemName, State newState) {
// the code being executed when a state was sent on the openHAB
// event bus goes here. This method is only called if one of the
// BindingProviders provide a binding for the given 'itemName'.
logger.debug("internalReceiveCommand() is called!");
}
protected void addBindingProvider(HMSBindingProvider bindingProvider) {
super.addBindingProvider(bindingProvider);
}
protected void removeBindingProvider(HMSBindingProvider bindingProvider) {
super.removeBindingProvider(bindingProvider);
}
@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
culHandlerLifecycle.config(config);
}
@Override
public void error(Exception e) {
logger.error("Received error from CUL instead fo data", e);
}
}