зеркало из https://github.com/mozilla/openhab.git
Merge 1.3.1 into default (which is 1.4 now)
This commit is contained in:
Коммит
b1677d05b6
|
@ -91,6 +91,14 @@ public class NotifyMyAndroid {
|
|||
return notifyMyAndroid(apiKey, event, description);
|
||||
}
|
||||
|
||||
@ActionDoc(text = "Send a notification to your Android device using the default api key", returns = "<code>true</code>, if successful and <code>false</code> otherwise.")
|
||||
public static boolean notifyMyAndroid(
|
||||
@ParamDoc(name = "event", text = "The event to notify") String event,
|
||||
@ParamDoc(name = "description", text = "A description of the event to notify") String description,
|
||||
@ParamDoc(name = "priority", text = "The priority of the notification") int priority) {
|
||||
return notifyMyAndroid(apiKey, event, description, priority);
|
||||
}
|
||||
|
||||
@ActionDoc(text = "Send a notification to your Android device", returns = "<code>true</code>, if successful and <code>false</code> otherwise.")
|
||||
public static boolean notifyMyAndroid(
|
||||
@ParamDoc(name = "apiKey", text = "apiKey to use for the notification") String apiKey,
|
||||
|
|
|
@ -76,18 +76,18 @@ public class NotifyMyAndroidActionService implements ActionService, ManagedServi
|
|||
* This can be used to trigger actions on the device
|
||||
*/
|
||||
private final static String PARAM_KEY_DEFAULT_URL = "defaultUrl";
|
||||
|
||||
private final static String REASON_CANT_PARSE_NUMBER = "Can't parse number";
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether this action is properly configured which means all
|
||||
* necessary configurations are set. This flag can be checked by the action
|
||||
* methods before executing code.
|
||||
*/
|
||||
/* default */static boolean isProperlyConfigured = false;
|
||||
|
||||
|
||||
|
||||
public NotifyMyAndroidActionService() {
|
||||
}
|
||||
|
||||
|
||||
public void activate() {
|
||||
logger.debug("NotifyMyAndroid action service activated");
|
||||
|
@ -96,6 +96,7 @@ public class NotifyMyAndroidActionService implements ActionService, ManagedServi
|
|||
public void deactivate() {
|
||||
logger.debug("NotifyMyAndroid action service deactivated");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getActionClassName() {
|
||||
|
@ -146,9 +147,10 @@ public class NotifyMyAndroidActionService implements ActionService, ManagedServi
|
|||
|
||||
NotifyMyAndroid.defaultUrl = (String) config.get(PARAM_KEY_DEFAULT_URL);
|
||||
} else {
|
||||
// We don't need necessarely any config
|
||||
logger.warn("Dictionary was NULL, didn't read any configuration");
|
||||
// We don't need necessarily any config
|
||||
logger.debug("Dictionary was NULL, didn't read any configuration");
|
||||
}
|
||||
|
||||
isProperlyConfigured = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<groupId>org.openhab.archetype</groupId>
|
||||
<artifactId>org.openhab.archetype.action</artifactId>
|
||||
<version>1.3.0-SNAPSHOT</version>
|
||||
<version>1.3.1-SNAPSHOT</version>
|
||||
<packaging>maven-archetype</packaging>
|
||||
|
||||
<name>org.openhab.archetype.action</name>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<groupId>org.openhab.archetype</groupId>
|
||||
<artifactId>org.openhab.archetype.binding</artifactId>
|
||||
<version>1.3.0-SNAPSHOT</version>
|
||||
<version>1.3.1-SNAPSHOT</version>
|
||||
<packaging>maven-archetype</packaging>
|
||||
|
||||
<name>org.openhab.archetype.binding</name>
|
||||
|
|
|
@ -1,10 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
openHAB, the open Home Automation Bus.
|
||||
Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
|
||||
See the contributors.txt file in the distribution for a
|
||||
full listing of individual contributors.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
Additional permission under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with Eclipse (or a modified version of that library),
|
||||
containing parts covered by the terms of the Eclipse Public License
|
||||
(EPL), the licensors of this Program grant you additional permission
|
||||
to convey the resulting work. -->
|
||||
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" enabled="true" immediate="true" name="org.openhab.binding.digitalstrom">
|
||||
<implementation class="org.openhab.binding.digitalstrom.internal.DigitalSTROMBinding"/>
|
||||
<reference bind="addBindingProvider" cardinality="1..n" interface="org.openhab.binding.digitalstrom.DigitalSTROMBindingProvider" name="DigitalSTROMBindingProvider" policy="dynamic" unbind="removeBindingProvider"/>
|
||||
<property name="event.topics" type="String" value="openhab/*"/>
|
||||
<service>
|
||||
|
||||
<service>
|
||||
<provide interface="org.osgi.service.event.EventHandler"/>
|
||||
<provide interface="org.osgi.service.cm.ManagedService"/>
|
||||
</service>
|
||||
|
||||
<property name="event.topics" type="String" value="openhab/command/*"/>
|
||||
<property name="service.pid" type="String" value="org.openhab.digitalstrom"/>
|
||||
<reference bind="addBindingProvider" cardinality="1..n" interface="org.openhab.binding.digitalstrom.DigitalSTROMBindingProvider" name="DigitalSTROMBindingProvider" policy="dynamic" unbind="removeBindingProvider"/>
|
||||
|
||||
<reference bind="setEventPublisher" cardinality="1..1" interface="org.openhab.core.events.EventPublisher" name="EventPublisher" policy="dynamic" unbind="unsetEventPublisher"/>
|
||||
|
||||
</scr:component>
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.openhab.binding.digitalstrom.internal.digitalstromgenericbindingprovider">
|
||||
<implementation class="org.openhab.binding.digitalstrom.internal.DigitalSTROMGenericBindingProvider"/>
|
||||
<service>
|
||||
<provide interface="org.openhab.binding.digitalstrom.DigitalSTROMBindingProvider"/>
|
||||
<provide interface="org.openhab.model.item.binding.BindingConfigReader"/>
|
||||
<provide interface="org.osgi.service.cm.ManagedService"/>
|
||||
<provide interface="org.openhab.binding.digitalstrom.DigitalSTROMBindingProvider"/>
|
||||
</service>
|
||||
<property name="service.pid" type="String" value="org.openhab.digitalstrom"/>
|
||||
</scr:component>
|
||||
|
|
|
@ -29,39 +29,34 @@
|
|||
*/
|
||||
package org.openhab.binding.digitalstrom;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.listener.ItemListener;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.config.DigitalSTROMBindingConfig;
|
||||
import org.openhab.core.binding.BindingProvider;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.items.Item;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface DigitalSTROMBindingProvider extends BindingProvider {
|
||||
|
||||
/**
|
||||
* Clean up (stopping threads,
|
||||
* deleting lists and maps)
|
||||
* Returns the configuration for the item with the given name.
|
||||
* @param itemName
|
||||
* @return The configuration if there is an item with the given name, null
|
||||
* otherwise.
|
||||
*/
|
||||
public void shutdownBinding();
|
||||
public DigitalSTROMBindingConfig getItemConfig(String itemName);
|
||||
|
||||
/**
|
||||
* Send command to digitalSTROM installation
|
||||
*
|
||||
* @param itemName name of openHAB-Item
|
||||
* @param cm openHAB command
|
||||
*/
|
||||
public void sendCommandToDSS(String itemName, Command cm);
|
||||
public List<String> getItemNamesByDsid(String dsid);
|
||||
|
||||
public Set<Item> getItemNamesByContext(String context);
|
||||
|
||||
public List<DigitalSTROMBindingConfig> getAllCircuitConsumptionItems();
|
||||
|
||||
public List<DigitalSTROMBindingConfig> getAllDeviceConsumptionItems();
|
||||
|
||||
// public String getToken();
|
||||
|
||||
public void addItemListener(ItemListener listener);
|
||||
|
||||
public void removeItemListener(ItemListener listener);
|
||||
|
||||
public void notifyItemListener(String itemName, State state);
|
||||
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class JSONResponseHandler {
|
||||
|
@ -79,4 +80,4 @@ public class JSONResponseHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -36,12 +36,12 @@ import java.net.MalformedURLException;
|
|||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
|
||||
//import org.openhab.io.net.http.HttpUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class HttpTransport {
|
||||
|
@ -66,15 +66,6 @@ public class HttpTransport {
|
|||
public String execute(String request, int connectTimeout, int readTimeout) {
|
||||
if (request != null && !request.trim().equals("")) {
|
||||
|
||||
|
||||
/* String response = HttpUtil.executeUrl("GET", this.uri+request, null, null, null, connectTimeout );
|
||||
if (response != null) {
|
||||
return response.toString();
|
||||
}
|
||||
else
|
||||
return null;*/
|
||||
|
||||
|
||||
HttpURLConnection connection = null;
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
@ -131,4 +122,4 @@ public class HttpTransport {
|
|||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class JSONDeviceImpl implements Device {
|
||||
|
@ -231,7 +232,12 @@ public class JSONDeviceImpl implements Device {
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setIsOn(boolean flag) {
|
||||
public void setIsOn(boolean flag) {
|
||||
//if device is off set power consumption and energy meter value to 0
|
||||
if(flag == false){
|
||||
this.powerConsumption=0;
|
||||
this.energyMeterValue=0;
|
||||
}
|
||||
this.isOn = flag;
|
||||
}
|
||||
|
||||
|
@ -504,4 +510,4 @@ public class JSONDeviceImpl implements Device {
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -61,6 +61,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
* @version digitalSTROM-API 1.14.5
|
||||
*/
|
||||
|
@ -1085,4 +1086,4 @@ public class DigitalSTROMJSONImpl implements DigitalSTROMAPI{
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.digitalstrom.internal.client.job;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.client.DigitalSTROMAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.client.constants.SensorIndexEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.Device;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class DeviceConsumptionSensorJob implements SensorJob {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(DeviceConsumptionSensorJob.class);
|
||||
private Device device = null;
|
||||
private SensorIndexEnum sensorIndex = null;
|
||||
|
||||
public DeviceConsumptionSensorJob(Device device, SensorIndexEnum index) {
|
||||
this.device = device;
|
||||
this.sensorIndex = index;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.openhab.binding.digitalSTROM2.internal.client.job.SensorJob#execute(org.openhab.binding.digitalSTROM2.internal.client.DigitalSTROMAPI, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void execute(DigitalSTROMAPI digitalSTROM, String token) {
|
||||
int consumption = digitalSTROM.getDeviceSensorValue(token, this.device.getDSID(), null, this.sensorIndex);
|
||||
logger.info("DeviceConsumption : "+consumption+", DSID: "+this.device.getDSID().getValue());
|
||||
|
||||
switch (this.sensorIndex) {
|
||||
|
||||
case ACTIVE_POWER:
|
||||
this.device.setPowerConsumption(consumption);
|
||||
break;
|
||||
case OUTPUT_CURRENT:
|
||||
this.device.setElectricMeterValue(consumption);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DeviceConsumptionSensorJob) {
|
||||
DeviceConsumptionSensorJob other = (DeviceConsumptionSensorJob) obj;
|
||||
String device = this.device.getDSID().getValue()+this.sensorIndex.getIndex();
|
||||
return device.equals(other.device.getDSID().getValue()+other.sensorIndex.getIndex());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDsid() {
|
||||
return device.getDSID();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.digitalstrom.internal.client.job;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.client.DigitalSTROMAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.Device;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class DeviceOutputValueSensorJob implements SensorJob {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(DeviceOutputValueSensorJob.class);
|
||||
private Device device = null;
|
||||
private short index = 0;
|
||||
|
||||
public DeviceOutputValueSensorJob(Device device, short index) {
|
||||
this.device = device;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.openhab.binding.digitalSTROM2.internal.client.job.SensorJob#execute(org.openhab.binding.digitalSTROM2.internal.client.DigitalSTROMAPI)
|
||||
*/
|
||||
@Override
|
||||
public void execute(DigitalSTROMAPI digitalSTROM, String token) {
|
||||
int value = digitalSTROM.getDeviceOutputValue(token, this.device.getDSID(), null, this.index);
|
||||
logger.info("DeviceOutputValue on Demand : "+value+", DSID: "+this.device.getDSID().getValue());
|
||||
|
||||
if (value != 1) {
|
||||
switch (this.index) {
|
||||
case 0:
|
||||
this.device.setOutputValue(value);
|
||||
break;
|
||||
case 4:
|
||||
this.device.setSlatPosition(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DeviceOutputValueSensorJob) {
|
||||
DeviceOutputValueSensorJob other = (DeviceOutputValueSensorJob) obj;
|
||||
String key = this.device.getDSID().getValue()+this.index;
|
||||
return key.equals((other.device.getDSID().getValue()+other.index));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDsid() {
|
||||
return device.getDSID();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.digitalstrom.internal.client.job;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.client.DigitalSTROMAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.client.constants.DeviceParameterClassEnum;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.Device;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DeviceConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class SceneOutputValueSensorJob implements SensorJob {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(SceneOutputValueSensorJob.class);
|
||||
|
||||
private Device device = null;
|
||||
private short sceneId = 0;
|
||||
|
||||
public SceneOutputValueSensorJob(Device device, short sceneId) {
|
||||
this.device = device;
|
||||
this.sceneId = sceneId;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.openhab.binding.digitalSTROM2.internal.client.job.SensorJob#execute(org.openhab.binding.digitalSTROM2.internal.client.DigitalSTROMAPI, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void execute(DigitalSTROMAPI digitalSTROM, String token) {
|
||||
DeviceConfig config = digitalSTROM.getDeviceConfig(token, this.device.getDSID(), null, DeviceParameterClassEnum.CLASS_128, this.sceneId);
|
||||
|
||||
if (config != null) {
|
||||
this.device.setSceneOutputValue(this.sceneId, (short) config.getValue());
|
||||
logger.info("UPDATED sceneOutputValue for dsid: "+this.device.getDSID()+", sceneID: "+sceneId+", value: "+config.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SceneOutputValueSensorJob) {
|
||||
SceneOutputValueSensorJob other = (SceneOutputValueSensorJob) obj;
|
||||
String str = other.device.getDSID().getValue()+"-"+other.sceneId;
|
||||
return (this.device.getDSID().getValue()+"-"+this.sceneId).equals(str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DSID getDsid() {
|
||||
return device.getDSID();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.digitalstrom.internal.client.job;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.client.DigitalSTROMAPI;
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
|
||||
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public interface SensorJob {
|
||||
public DSID getDsid();
|
||||
public void execute(DigitalSTROMAPI digitalSTROM, String token);
|
||||
|
||||
}
|
|
@ -1,3 +1,31 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.digitalstrom.internal.config;
|
||||
|
||||
import org.openhab.binding.digitalstrom.internal.client.entity.DSID;
|
||||
|
@ -9,20 +37,24 @@ import org.openhab.model.item.binding.BindingConfigParseException;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DigitalSTROMBindingConfigItem implements BindingConfig {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DigitalSTROMBindingConfigItem.class);
|
||||
/**
|
||||
* @author Alexander Betker
|
||||
* @author Alex Maier
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class DigitalSTROMBindingConfig implements BindingConfig{
|
||||
private static final Logger logger = LoggerFactory.getLogger(DigitalSTROMBindingConfig.class);
|
||||
|
||||
public String itemName = null;
|
||||
private Item item=null;
|
||||
public Item item=null;
|
||||
public DSID dsid = null;
|
||||
public DSID dsmid = null;
|
||||
public ConsumptionConfig consumption = null;
|
||||
public ConsumptionConfig consumption = ConsumptionConfig.ACTIVE_POWER;
|
||||
public int timeinterval = 0;
|
||||
public ContextConfig context = null;
|
||||
public short groupID = -1;
|
||||
public int zoneID = -1;
|
||||
public DigitalSTROMBindingConfigItem() {
|
||||
public DigitalSTROMBindingConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
@ -158,5 +190,11 @@ public class DigitalSTROMBindingConfigItem implements BindingConfig {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean isValidDeviceMeterItem() {
|
||||
if (this.dsid != null) {
|
||||
return (item instanceof NumberItem || item instanceof StringItem);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package org.openhab.binding.digitalstrom.internal.listener;
|
||||
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
public interface ItemListener {
|
||||
|
||||
public void itemStateUpdated(String itemName, State state);
|
||||
|
||||
}
|
Двоичный файл не отображается.
|
@ -215,6 +215,10 @@ public class EnoceanBinding extends AbstractBinding<EnoceanBindingProvider> impl
|
|||
EEPId eep = enoceanBindingProvider.getEEP(itemName);
|
||||
esp3Host.addDeviceProfile(parameterAddress.getEnoceanDeviceId(), eep);
|
||||
Item item = enoceanBindingProvider.getItem(itemName);
|
||||
if (profiles.containsKey(parameterAddress.getAsString())) {
|
||||
Profile profile = profiles.get(parameterAddress.getAsString());
|
||||
profile.removeItem(item);
|
||||
}
|
||||
Class<Profile> customProfileClass = enoceanBindingProvider.getCustomProfile(itemName);
|
||||
if (customProfileClass != null) {
|
||||
Constructor<Profile> constructor;
|
||||
|
@ -228,25 +232,16 @@ public class EnoceanBinding extends AbstractBinding<EnoceanBindingProvider> impl
|
|||
}
|
||||
} else if (RockerSwitch.EEP_ID_1.equals(eep) || RockerSwitch.EEP_ID_2.equals(eep)) {
|
||||
if (item.getClass().equals(RollershutterItem.class)) {
|
||||
addRollershutterProfile(enoceanBindingProvider, itemName, parameterAddress);
|
||||
RollershutterProfile profile = new RollershutterProfile(item, eventPublisher);
|
||||
addProfile(item, parameterAddress, profile);
|
||||
}
|
||||
if (item.getClass().equals(DimmerItem.class)) {
|
||||
addDimmerProfile(enoceanBindingProvider, itemName, parameterAddress);
|
||||
DimmerOnOffProfile profile = new DimmerOnOffProfile(item, eventPublisher);
|
||||
addProfile(item, parameterAddress, profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRollershutterProfile(EnoceanBindingProvider enoceanBindingProvider, String itemName,
|
||||
EnoceanParameterAddress parameterAddress) {
|
||||
RollershutterProfile profile = new RollershutterProfile(enoceanBindingProvider.getItem(itemName), eventPublisher);
|
||||
addProfile(enoceanBindingProvider.getItem(itemName), parameterAddress, profile);
|
||||
}
|
||||
|
||||
private void addDimmerProfile(EnoceanBindingProvider enoceanBindingProvider, String itemName, EnoceanParameterAddress parameterAddress) {
|
||||
DimmerOnOffProfile profile = new DimmerOnOffProfile(enoceanBindingProvider.getItem(itemName), eventPublisher);
|
||||
addProfile(enoceanBindingProvider.getItem(itemName), parameterAddress, profile);
|
||||
}
|
||||
|
||||
private void addProfile(Item item, ParameterAddress parameterAddress, Profile profile) {
|
||||
if (profiles.containsKey(parameterAddress.getAsString())) {
|
||||
profiles.get(parameterAddress.getAsString()).addItem(item);
|
||||
|
|
|
@ -66,4 +66,9 @@ public abstract class BasicProfile implements Profile {
|
|||
items.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeItem(Item item) {
|
||||
items.remove(item);
|
||||
}
|
||||
|
||||
}
|
|
@ -44,4 +44,6 @@ public interface Profile extends ParameterValueChangeListener {
|
|||
|
||||
void addItem(Item item);
|
||||
|
||||
void removeItem(Item item);
|
||||
|
||||
}
|
|
@ -221,7 +221,7 @@ public class IhcBinding extends AbstractActiveBinding<IhcBindingProvider>
|
|||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn("Controller is null => refresh cycle aborted!");
|
||||
logger.debug("Controller is null => refresh cycle aborted!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="/org.openhab.io.transport.serial/lib/nrjavaserial-3.8.8.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -34,13 +34,17 @@
|
|||
<implementation class="org.openhab.binding.modbus.internal.ModbusBinding"/>
|
||||
|
||||
<service>
|
||||
<provide interface="org.openhab.binding.modbus.internal.ModbusBinding"/>
|
||||
<provide interface="org.osgi.service.cm.ManagedService"/>
|
||||
<provide interface="org.osgi.service.event.EventHandler"/>
|
||||
</service>
|
||||
|
||||
<property name="event.topics" type="String" value="openhab/*"/>
|
||||
<property name="service.pid" type="String" value="org.openhab.modbus"/>
|
||||
<property name="event.topics" type="String" value="openhab/*"/>
|
||||
|
||||
<reference bind="setEventPublisher" cardinality="1..1" interface="org.openhab.core.events.EventPublisher" name="EventPublisher" policy="dynamic" unbind="unsetEventPublisher"/>
|
||||
<reference bind="addBindingProvider" cardinality="1..n" interface="org.openhab.binding.modbus.ModbusBindingProvider" name="ModbusBindingProvider" policy="dynamic" unbind="removeBindingProvider"/>
|
||||
<reference bind="setEventPublisher" cardinality="1..1"
|
||||
interface="org.openhab.core.events.EventPublisher" name="EventPublisher"
|
||||
policy="dynamic" unbind="unsetEventPublisher"/>
|
||||
<reference bind="addBindingProvider" cardinality="1..n"
|
||||
interface="org.openhab.binding.modbus.ModbusBindingProvider" name="ModbusBindingProvider"
|
||||
policy="dynamic" unbind="removeBindingProvider"/>
|
||||
</scr:component>
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
openHAB, the open Home Automation Bus.
|
||||
Copyright (C) 2011, openHAB.org <admin@openhab.org>
|
||||
|
||||
See the contributors.txt file in the distribution for a
|
||||
full listing of individual contributors.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
Additional permission under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with Eclipse (or a modified version of that library),
|
||||
containing parts covered by the terms of the Eclipse Public License
|
||||
(EPL), the licensors of this Program grant you additional permission
|
||||
to convey the resulting work.
|
||||
|
||||
-->
|
||||
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="true" name="org.openhab.binding.modbusconfiguration">
|
||||
<implementation class="org.openhab.binding.modbus.internal.ModbusConfiguration"/>
|
||||
<property name="service.pid" type="String" value="org.openhab.modbus"/>
|
||||
<service>
|
||||
<provide interface="org.osgi.service.cm.ManagedService"/>
|
||||
</service>
|
||||
<!--
|
||||
|
||||
<reference bind="setModbusBinding" cardinality="1..1" interface="org.openhab.binding.modbus.internal.ModbusBinding" name="ModbusBinding" policy="dynamic" unbind="unsetModbusBinding"/>
|
||||
<property name="event.topics" type="String" value="openhab/*"/>
|
||||
-->
|
||||
</scr:component>
|
|
@ -1,41 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
openHAB, the open Home Automation Bus.
|
||||
Copyright (C) 2011, openHAB.org <admin@openhab.org>
|
||||
|
||||
See the contributors.txt file in the distribution for a
|
||||
full listing of individual contributors.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
|
||||
Additional permission under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with Eclipse (or a modified version of that library),
|
||||
containing parts covered by the terms of the Eclipse Public License
|
||||
(EPL), the licensors of this Program grant you additional permission
|
||||
to convey the resulting work.
|
||||
|
||||
-->
|
||||
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" enabled="true" name="org.openhab.binding.modbuspoll">
|
||||
<implementation class="org.openhab.binding.modbus.internal.ModbusPoll"/>
|
||||
|
||||
<reference bind="setModbusBinding" cardinality="1..1" interface="org.openhab.binding.modbus.internal.ModbusBinding" name="ModbusBinding" policy="dynamic" unbind="unsetModbusBinding"/>
|
||||
<!--
|
||||
<property name="event.topics" type="String" value="openhab/*"/>
|
||||
-->
|
||||
<property name="service.pid" type="String" value="org.openhab.modbuspoll"/>
|
||||
</scr:component>
|
|
@ -66,7 +66,7 @@ public class LinkedQueue {
|
|||
}
|
||||
}//insert
|
||||
|
||||
/** Main mechanics for take/poll **/
|
||||
/** Main mechanics for take/pollInterval **/
|
||||
protected synchronized Object extract() {
|
||||
synchronized (m_Head) {
|
||||
Object x = null;
|
||||
|
@ -174,7 +174,7 @@ public class LinkedQueue {
|
|||
}
|
||||
}
|
||||
}
|
||||
}//poll
|
||||
}//pollInterval
|
||||
|
||||
|
||||
}//LinkedQueue
|
||||
|
|
|
@ -29,19 +29,32 @@
|
|||
package org.openhab.binding.modbus.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.wimpi.modbus.procimg.InputRegister;
|
||||
import net.wimpi.modbus.util.BitVector;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openhab.binding.modbus.ModbusBindingProvider;
|
||||
import org.openhab.binding.modbus.internal.ModbusGenericBindingProvider.ModbusBindingConfig;
|
||||
import org.openhab.core.binding.AbstractBinding;
|
||||
import org.openhab.core.binding.AbstractActiveBinding;
|
||||
import org.openhab.core.binding.BindingProvider;
|
||||
import org.openhab.core.library.items.SwitchItem;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.osgi.service.cm.ConfigurationException;
|
||||
import org.osgi.service.cm.ManagedService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -51,13 +64,40 @@ import org.openhab.core.types.State;
|
|||
* @author Dmitry Krasnov
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class ModbusBinding extends AbstractBinding<ModbusBindingProvider> {
|
||||
public class ModbusBinding extends AbstractActiveBinding<ModbusBindingProvider> implements ManagedService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ModbusBinding.class);
|
||||
|
||||
private static final String TCP_PREFIX = "tcp";
|
||||
private static final String SERIAL_PREFIX = "serial";
|
||||
|
||||
private static final Pattern EXTRACT_MODBUS_CONFIG_PATTERN =
|
||||
Pattern.compile("^("+TCP_PREFIX+"|"+SERIAL_PREFIX+"|)\\.(.*?)\\.(connection|id|pollInterval|start|length|type)$");
|
||||
|
||||
/** Stores instances of all the slaves defined in cfg file */
|
||||
private static Map<String, ModbusSlave> modbusSlaves = new ConcurrentHashMap<String, ModbusSlave>();
|
||||
|
||||
/** slaves update interval in milliseconds, defaults to 200ms */
|
||||
public static int pollInterval = 200;
|
||||
|
||||
|
||||
public void activate() {
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected long getRefreshInterval() {
|
||||
return pollInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName() {
|
||||
return "Modbus Polling Service";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses configuration creating Modbus slave instances defined in cfg file
|
||||
|
@ -67,7 +107,7 @@ public class ModbusBinding extends AbstractBinding<ModbusBindingProvider> {
|
|||
for (ModbusBindingProvider provider : providers) {
|
||||
if (provider.providesBindingFor(itemName)) {
|
||||
ModbusBindingConfig config = provider.getConfig(itemName);
|
||||
ModbusSlave slave = ModbusConfiguration.getSlave(config.slaveName);
|
||||
ModbusSlave slave = modbusSlaves.get(config.slaveName);
|
||||
slave.executeCommand(command, config.readRegister, config.writeRegister);
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +116,7 @@ public class ModbusBinding extends AbstractBinding<ModbusBindingProvider> {
|
|||
/**
|
||||
* Posts update event to OpenHAB bus for "holding" type slaves
|
||||
* @param binding ModbusBinding to get item configuration from BindingProviding
|
||||
* @param registers data received from slave device in the last poll
|
||||
* @param registers data received from slave device in the last pollInterval
|
||||
* @param itemName item to update
|
||||
*/
|
||||
protected void internalUpdateItem(String slaveName, InputRegister[] registers,
|
||||
|
@ -105,7 +145,7 @@ public class ModbusBinding extends AbstractBinding<ModbusBindingProvider> {
|
|||
/**
|
||||
* Posts update event to OpenHAB bus for "coil" type slaves
|
||||
* @param binding ModbusBinding to get item configuration from BindingProviding
|
||||
* @param registers data received from slave device in the last poll
|
||||
* @param registers data received from slave device in the last pollInterval
|
||||
* @param item item to update
|
||||
*/
|
||||
protected void internalUpdateItem(String slaveName, BitVector coils,
|
||||
|
@ -140,4 +180,112 @@ public class ModbusBinding extends AbstractBinding<ModbusBindingProvider> {
|
|||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* updates all slaves from the modbusSlaves
|
||||
*/
|
||||
@Override
|
||||
protected void execute() {
|
||||
Collection<ModbusSlave> slaves = new HashSet<ModbusSlave>();
|
||||
synchronized (slaves) {
|
||||
slaves.addAll(modbusSlaves.values());
|
||||
}
|
||||
for (ModbusSlave slave : slaves) {
|
||||
slave.update(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
|
||||
// remove all known items if configuration changed
|
||||
modbusSlaves.clear();
|
||||
|
||||
if (config != null) {
|
||||
Enumeration<String> keys = config.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String key = (String) keys.nextElement();
|
||||
|
||||
// the config-key enumeration contains additional keys that we
|
||||
// don't want to process here ...
|
||||
if ("service.pid".equals(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher matcher = EXTRACT_MODBUS_CONFIG_PATTERN.matcher(key);
|
||||
if (!matcher.matches()) {
|
||||
if ("poll".equals(key)) {
|
||||
if (StringUtils.isNotBlank((String) config.get(key))) {
|
||||
pollInterval = Integer.valueOf((String) config.get(key));
|
||||
}
|
||||
} else if ("writemultipleregisters".equals(key)) {
|
||||
ModbusSlave.setWriteMultipleRegisters(Boolean.valueOf(config.get(key).toString()));
|
||||
} else {
|
||||
logger.debug("given modbus-slave-config-key '" + key
|
||||
+ "' does not follow the expected pattern 'pollInterval' or '<slaveId>.<connection|id|start|length|type>'");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
matcher.reset();
|
||||
matcher.find();
|
||||
|
||||
String slave = matcher.group(2);
|
||||
|
||||
ModbusSlave modbusSlave = modbusSlaves.get(slave);
|
||||
if (modbusSlave == null) {
|
||||
if (matcher.group(1).equals(TCP_PREFIX)) {
|
||||
modbusSlave = new ModbusTcpSlave(slave);
|
||||
} else if (matcher.group(1).equals(SERIAL_PREFIX)) {
|
||||
modbusSlave = new ModbusSerialSlave(slave);
|
||||
} else {
|
||||
throw new ConfigurationException(slave, "the given slave type '" + slave + "' is unknown");
|
||||
}
|
||||
modbusSlaves.put(slave,modbusSlave);
|
||||
}
|
||||
|
||||
String configKey = matcher.group(3);
|
||||
String value = (String) config.get(key);
|
||||
|
||||
if ("connection".equals(configKey)) {
|
||||
String[] chunks = value.split(":");
|
||||
if (modbusSlave instanceof ModbusTcpSlave) {
|
||||
((ModbusTcpSlave) modbusSlave).setHost(chunks[0]);
|
||||
if (chunks.length == 2) {
|
||||
((ModbusTcpSlave) modbusSlave).setPort(Integer.valueOf(chunks[1]));
|
||||
}
|
||||
} else if (modbusSlave instanceof ModbusSerialSlave) {
|
||||
((ModbusSerialSlave) modbusSlave).setPort(chunks[0]);
|
||||
if (chunks.length == 2) {
|
||||
((ModbusSerialSlave) modbusSlave).setBaud(Integer.valueOf(chunks[1]));
|
||||
}
|
||||
}
|
||||
} else if ("start".equals(configKey)) {
|
||||
modbusSlave.setStart(Integer.valueOf(value));
|
||||
} else if ("length".equals(configKey)) {
|
||||
modbusSlave.setLength(Integer.valueOf(value));
|
||||
} else if ("id".equals(configKey)) {
|
||||
modbusSlave.setId(Integer.valueOf(value));
|
||||
} else if ("type".equals(configKey)) {
|
||||
if (ArrayUtils.contains(ModbusBindingProvider.SLAVE_DATA_TYPES, value)) {
|
||||
modbusSlave.setType(value);
|
||||
} else {
|
||||
throw new ConfigurationException(configKey, "the given slave type '" + value + "' is invalid");
|
||||
}
|
||||
} else {
|
||||
throw new ConfigurationException(configKey,
|
||||
"the given configKey '" + configKey + "' is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
// connect instances to modbus slaves
|
||||
for (ModbusSlave slave : modbusSlaves.values()) {
|
||||
slave.connect();
|
||||
}
|
||||
|
||||
setProperlyConfigured(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,217 +0,0 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.modbus.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.openhab.binding.modbus.ModbusBindingProvider;
|
||||
import org.osgi.service.cm.ConfigurationException;
|
||||
import org.osgi.service.cm.ManagedService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Entries in openhab config file should look like below. Most of config
|
||||
* parameters are related to specific slaves, the only exception is
|
||||
* <p>
|
||||
* modbus:poll=<value>
|
||||
* </p>
|
||||
* which sets refresh interval to Modbus polling service. Value in milliseconds
|
||||
* - optional, default is 200
|
||||
* <p>
|
||||
* modbus:<slave-type>.<slave-name>.<slave-parameter>
|
||||
* </p><p>
|
||||
* <slave-type> should be either "tcp" or "serial".
|
||||
* <slave-name> is unique name per slave you are connecting to.
|
||||
* <slave-parameter> are pairs key=value
|
||||
* </p><p>
|
||||
* Valid keys are
|
||||
* <ul>
|
||||
* <li>connection - mandatory. For tcp slaves connection should be ip address or ip:port,
|
||||
* if port is omitted it is defaulted to 502. For serial slave connection should be com-port-name or com-port-name:baud, if baud is omitted it is defaulted to 9600</li>
|
||||
* <li>id - slave id, optional, default 1</li>
|
||||
* <li>start - slave start address, optional, default 0</li>
|
||||
* <li>length - number of data item to read, default 0 (but set it to something meaningful :)</li>
|
||||
* <li>type - data type, can be "coil" "discrete" "holding" "input"</li>
|
||||
* </ul>
|
||||
* </p><p>
|
||||
* Minimal construction in openhab.config will look like
|
||||
* <pre>
|
||||
* modbus:tcp.slave1.connection=192.168.1.50
|
||||
* modbus:tcp.slave1.length=10
|
||||
* modbus:tcp.slave1.type=coil
|
||||
* </pre>
|
||||
* connects to slave on ip=192.168.1.51 and reads 10 coils starting from address 0.
|
||||
* <p>
|
||||
* More complex setup could look like
|
||||
* <pre>
|
||||
* modbus:poll=300
|
||||
* modbus:serial.slave1.connection=COM15:19200
|
||||
* modbus:serial.slave1.id=41
|
||||
* modbus:serial.slave1.start=0
|
||||
* modbus:seria.slave1.length=32
|
||||
* modbus:serial.slave1.type=coil
|
||||
* </pre>
|
||||
* @author Dmitry Krasnov
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class ModbusConfiguration implements ManagedService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ModbusConfiguration.class);
|
||||
|
||||
private static final String TCP_PREFIX = "tcp";
|
||||
private static final String SERIAL_PREFIX = "serial";
|
||||
|
||||
private static final Pattern EXTRACT_MODBUS_CONFIG_PATTERN =
|
||||
Pattern.compile("^("+TCP_PREFIX+"|"+SERIAL_PREFIX+"|)\\.(.*?)\\.(connection|id|poll|start|length|type)$");
|
||||
|
||||
/** Stores instances of all the slaves defined in cfg file */
|
||||
private static Map<String, ModbusSlave> modbusSlaves = Collections.synchronizedMap(new HashMap<String, ModbusSlave>());
|
||||
|
||||
/** slaves update interval in milliseconds */
|
||||
public static int poll = 0;
|
||||
|
||||
|
||||
public int getPoll() {
|
||||
return poll;
|
||||
}
|
||||
|
||||
public static ModbusSlave getSlave(String slave) {
|
||||
return Collections.synchronizedMap(modbusSlaves).get(slave);
|
||||
}
|
||||
|
||||
public static Collection<ModbusSlave> getAllSlaves() {
|
||||
return Collections.synchronizedMap(modbusSlaves).values();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void updated(Dictionary config) throws ConfigurationException {
|
||||
|
||||
// remove all known items if configuration changed
|
||||
Collections.synchronizedMap(modbusSlaves).clear();
|
||||
|
||||
if (config != null) {
|
||||
|
||||
Enumeration keys = config.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
|
||||
String key = (String) keys.nextElement();
|
||||
|
||||
// the config-key enumeration contains additional keys that we
|
||||
// don't want to process here ...
|
||||
if ("service.pid".equals(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher matcher = EXTRACT_MODBUS_CONFIG_PATTERN.matcher(key);
|
||||
if (!matcher.matches()) {
|
||||
if ("poll".equals(key)) {
|
||||
poll = Integer.valueOf((String) config.get(key));
|
||||
} else if ("writemultipleregisters".equals(key)) {
|
||||
ModbusSlave.setWriteMultipleRegisters(Boolean.valueOf(config.get(key).toString()));
|
||||
} else {
|
||||
logger.debug("given modbus-slave-config-key '"
|
||||
+ key
|
||||
+ "' does not follow the expected pattern 'poll' or '<slaveId>.<connection|id|start|length|type>'");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
matcher.reset();
|
||||
matcher.find();
|
||||
|
||||
String slave = matcher.group(2);
|
||||
|
||||
ModbusSlave modbusSlave = Collections.synchronizedMap(modbusSlaves).get(slave);
|
||||
if (modbusSlave == null) {
|
||||
if (matcher.group(1).equals(TCP_PREFIX)) {
|
||||
modbusSlave = new ModbusTcpSlave(slave);
|
||||
} else
|
||||
if (matcher.group(1).equals(SERIAL_PREFIX)) {
|
||||
modbusSlave = new ModbusSerialSlave(slave);
|
||||
} else throw new ConfigurationException(slave,
|
||||
"the given slave type '" + slave + "' is unknown");
|
||||
|
||||
Collections.synchronizedMap(modbusSlaves).put(slave, modbusSlave);
|
||||
}
|
||||
|
||||
String configKey = matcher.group(3);
|
||||
String value = (String) config.get(key);
|
||||
if ("connection".equals(configKey)) {
|
||||
String [] chunks = value.split(":");
|
||||
if (modbusSlave instanceof ModbusTcpSlave) {
|
||||
((ModbusTcpSlave)modbusSlave).setHost(chunks[0]);
|
||||
if (chunks.length == 2) {
|
||||
((ModbusTcpSlave)modbusSlave).setPort(Integer.valueOf(chunks[1]));
|
||||
}
|
||||
} else if (modbusSlave instanceof ModbusSerialSlave) {
|
||||
((ModbusSerialSlave)modbusSlave).setPort(chunks[0]);
|
||||
if (chunks.length == 2) {
|
||||
((ModbusSerialSlave)modbusSlave).setBaud(Integer.valueOf(chunks[1]));
|
||||
}
|
||||
|
||||
}
|
||||
} else if ("start".equals(configKey)) {
|
||||
modbusSlave.setStart(Integer.valueOf(value));
|
||||
} else if ("length".equals(configKey)) {
|
||||
modbusSlave.setLength(Integer.valueOf(value));
|
||||
} else if ("id".equals(configKey)) {
|
||||
modbusSlave.setId(Integer.valueOf(value));
|
||||
} else if ("type".equals(configKey)) {
|
||||
if (ArrayUtils.contains(ModbusBindingProvider.SLAVE_DATA_TYPES, value)) {
|
||||
modbusSlave.setType(value);
|
||||
}
|
||||
else {
|
||||
throw new ConfigurationException(configKey,
|
||||
"the given slave type '" + value + "' is invalid");
|
||||
}
|
||||
} else {
|
||||
throw new ConfigurationException(configKey,
|
||||
"the given configKey '" + configKey + "' is unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// connect instances to modbus slaves
|
||||
for (ModbusSlave slave : Collections.synchronizedMap(modbusSlaves).values()) {
|
||||
slave.connect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/**
|
||||
* openHAB, the open Home Automation Bus.
|
||||
* Copyright (C) 2010-2013, openHAB.org <admin@openhab.org>
|
||||
*
|
||||
* See the contributors.txt file in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
||||
*
|
||||
* Additional permission under GNU GPL version 3 section 7
|
||||
*
|
||||
* If you modify this Program, or any covered work, by linking or
|
||||
* combining it with Eclipse (or a modified version of that library),
|
||||
* containing parts covered by the terms of the Eclipse Public License
|
||||
* (EPL), the licensors of this Program grant you additional permission
|
||||
* to convey the resulting work.
|
||||
*/
|
||||
package org.openhab.binding.modbus.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.openhab.core.service.AbstractActiveService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Modbus polling service that reads information from modbus slave devices
|
||||
*
|
||||
* @author Dmitry Krasnov
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class ModbusPoll extends AbstractActiveService {
|
||||
|
||||
static final Logger logger = LoggerFactory.getLogger(ModbusPoll.class);
|
||||
|
||||
/**
|
||||
* ModbusBinding that stores information about items to be updated
|
||||
*/
|
||||
ModbusBinding binding = null;
|
||||
|
||||
public void setModbusBinding(ModbusBinding binding) {
|
||||
this.binding = binding;
|
||||
setProperlyConfigured(!ModbusConfiguration.getAllSlaves().isEmpty());
|
||||
}
|
||||
|
||||
public void unsetModbusBinding(ModbusBinding binding) {
|
||||
this.binding = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getRefreshInterval() {
|
||||
return ModbusConfiguration.poll;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName() {
|
||||
return "Modbus Polling Service";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
/**
|
||||
* updates all slaves from the modbusSlaves
|
||||
*/
|
||||
protected void execute() {
|
||||
Collection<ModbusSlave> slaves = new HashSet<ModbusSlave>();
|
||||
synchronized (slaves) {
|
||||
slaves.addAll(ModbusConfiguration.getAllSlaves());
|
||||
}
|
||||
for (ModbusSlave slave : slaves) {
|
||||
slave.update(binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -43,7 +43,6 @@ import net.wimpi.modbus.msg.ReadMultipleRegistersRequest;
|
|||
import net.wimpi.modbus.msg.ReadMultipleRegistersResponse;
|
||||
import net.wimpi.modbus.msg.WriteCoilRequest;
|
||||
import net.wimpi.modbus.msg.WriteMultipleRegistersRequest;
|
||||
import net.wimpi.modbus.msg.WriteMultipleRegistersResponse;
|
||||
import net.wimpi.modbus.msg.WriteSingleRegisterRequest;
|
||||
import net.wimpi.modbus.procimg.InputRegister;
|
||||
import net.wimpi.modbus.procimg.Register;
|
||||
|
|
|
@ -94,6 +94,11 @@ public class NikobusCommandParserTest {
|
|||
receivedCmds.add(new NikobusCommand(command.getCommand(),
|
||||
command.getRepeats()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "dummy";
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : values) {
|
||||
|
|
|
@ -417,12 +417,12 @@ public class NikobusBinding extends AbstractBinding<NikobusBindingProvider> impl
|
|||
@Override
|
||||
public void allBindingsChanged(BindingProvider provider) {
|
||||
|
||||
// clear all previous listeners..
|
||||
commandReceiver.unregisterAll();
|
||||
|
||||
NikobusBindingProvider bindingProvider = (NikobusBindingProvider) provider;
|
||||
for (String itemName : provider.getItemNames()) {
|
||||
if (!provider.providesBindingFor(itemName)) {
|
||||
log.trace("Removing command listener for item {}", itemName);
|
||||
unregister(bindingProvider.getItemConfig(itemName));
|
||||
} else {
|
||||
if (provider.providesBindingFor(itemName)) {
|
||||
register(bindingProvider.getItemConfig(itemName));
|
||||
log.trace("Registering command listener for item {} ", itemName);
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ public class NikobusBinding extends AbstractBinding<NikobusBindingProvider> impl
|
|||
NikobusBindingProvider bindingProvider = (NikobusBindingProvider) provider;
|
||||
if (!provider.providesBindingFor(itemName)) {
|
||||
log.trace("Removing command listener for item {}", itemName);
|
||||
unregister(bindingProvider.getItemConfig(itemName));
|
||||
commandReceiver.unregisterItem(itemName);
|
||||
} else {
|
||||
log.trace("Registering command listener for item {} ", itemName);
|
||||
register(bindingProvider.getItemConfig(itemName));
|
||||
|
|
|
@ -246,7 +246,7 @@ public class SwitchModuleChannelGroup implements NikobusModule {
|
|||
|
||||
log.debug(
|
||||
"Processing nikobus command {} for module ({}-{})",
|
||||
new String[] { cmd.getCommand(), address,
|
||||
new Object[] { cmd.getCommand(), address,
|
||||
Integer.toString(group) });
|
||||
lastUpdatedTime = System.currentTimeMillis();
|
||||
|
||||
|
@ -292,4 +292,9 @@ public class SwitchModuleChannelGroup implements NikobusModule {
|
|||
return addChecksumToCommand(cmd, binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return address + "-" + group;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
package org.openhab.binding.nikobus.internal.core;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -51,13 +52,15 @@ public class NikobusAckMonitor implements NikobusCommandListener {
|
|||
|
||||
private LinkedBlockingQueue<String> receivedCommands = new LinkedBlockingQueue<String>();
|
||||
|
||||
private String name = UUID.randomUUID().toString();
|
||||
|
||||
/**
|
||||
* Create a new monitor for an ACK command.
|
||||
*
|
||||
* @param command
|
||||
* for which to monitor an ACK
|
||||
*/
|
||||
public NikobusAckMonitor(NikobusCommand command) {
|
||||
public NikobusAckMonitor(NikobusCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
|
@ -143,5 +146,10 @@ public class NikobusAckMonitor implements NikobusCommandListener {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,13 @@ public interface NikobusCommandListener {
|
|||
* @param command
|
||||
* as it was read from serial port without CR.
|
||||
*/
|
||||
public void processNikobusCommand(NikobusCommand command, NikobusBinding binding);
|
||||
|
||||
public void processNikobusCommand(NikobusCommand command,
|
||||
NikobusBinding binding);
|
||||
|
||||
/**
|
||||
* Get the name of the item.
|
||||
*
|
||||
* @return item name
|
||||
*/
|
||||
public String getName();
|
||||
}
|
||||
|
|
|
@ -237,5 +237,30 @@ public class NikobusCommandReceiver implements Runnable {
|
|||
public void stop() {
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all registered command listeners.
|
||||
*/
|
||||
public void unregisterAll() {
|
||||
List<NikobusCommandListener> newListeners = new ArrayList<NikobusCommandListener>();
|
||||
atomicListReference.set(newListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an command listener by name
|
||||
* @param itemName
|
||||
*/
|
||||
public void unregisterItem(String itemName) {
|
||||
List<NikobusCommandListener> currentListeners = atomicListReference.get();
|
||||
List<NikobusCommandListener> newListeners = new ArrayList<NikobusCommandListener>();
|
||||
|
||||
for (NikobusCommandListener listener : currentListeners) {
|
||||
if (listener.getName().equals(itemName)) {
|
||||
continue;
|
||||
}
|
||||
newListeners.add(listener);
|
||||
}
|
||||
atomicListReference.set(newListeners);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -377,8 +377,6 @@ public class SysteminfoBinding extends AbstractActiveBinding<SysteminfoBindingPr
|
|||
*/
|
||||
@Override
|
||||
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
|
||||
logger.debug("Configuration updated, config {}", config != null ? true : false);
|
||||
|
||||
if (config != null) {
|
||||
String granularityString = (String) config.get("granularity");
|
||||
if (StringUtils.isNotBlank(granularityString)) {
|
||||
|
@ -401,16 +399,13 @@ public class SysteminfoBinding extends AbstractActiveBinding<SysteminfoBindingPr
|
|||
}
|
||||
|
||||
logger.debug("Using units: {}", units);
|
||||
|
||||
initializeSystemMonitor();
|
||||
|
||||
setProperlyConfigured(true);
|
||||
|
||||
}
|
||||
|
||||
initializeSystemMonitor();
|
||||
setProperlyConfigured(true);
|
||||
}
|
||||
|
||||
private void initializeSystemMonitor() {
|
||||
|
||||
if (sigarImpl == null) {
|
||||
sigarImpl = new Sigar();
|
||||
}
|
||||
|
@ -422,7 +417,6 @@ public class SysteminfoBinding extends AbstractActiveBinding<SysteminfoBindingPr
|
|||
logger.info("Using Sigar version {}", Sigar.VERSION_STRING);
|
||||
|
||||
try {
|
||||
|
||||
String[] interfaces = sigar.getNetInterfaceList();
|
||||
logger.debug("valid net interfaces: {}", Arrays.toString(interfaces));
|
||||
|
||||
|
@ -438,7 +432,6 @@ public class SysteminfoBinding extends AbstractActiveBinding<SysteminfoBindingPr
|
|||
}
|
||||
|
||||
logger.debug("valid disk names: {}", Arrays.toString(disks.toArray()));
|
||||
|
||||
} catch (SigarException e) {
|
||||
logger.error("System monitor error: {}", e);
|
||||
}
|
||||
|
|
|
@ -33,16 +33,16 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage;
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageClass;
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessagePriority;
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageType;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveController;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveNode;
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageClass;
|
||||
import org.openhab.binding.zwave.internal.protocol.SerialMessage.SerialMessageType;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Basic;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Generic;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveDeviceClass.Specific;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveEndpoint;
|
||||
import org.openhab.binding.zwave.internal.protocol.ZWaveNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -290,6 +290,8 @@ public class ZWaveMultiInstanceCommandClass extends ZWaveCommandClass {
|
|||
int startId = this.endpointsAreTheSameDeviceClass ? 1 : receivedEndpointId;
|
||||
int endId = this.endpointsAreTheSameDeviceClass ? this.endpoints.size() : receivedEndpointId;
|
||||
|
||||
boolean supportsBasicCommandClass = this.getNode().supportsCommandClass(CommandClass.BASIC);
|
||||
|
||||
for (int endpointId = startId; endpointId <= endId; endpointId++) {
|
||||
ZWaveEndpoint endpoint = this.endpoints.get(endpointId);
|
||||
|
||||
|
@ -323,6 +325,12 @@ public class ZWaveMultiInstanceCommandClass extends ZWaveCommandClass {
|
|||
deviceClass.setGenericDeviceClass(generic);
|
||||
deviceClass.setSpecificDeviceClass(specific);
|
||||
|
||||
// add basic command class, if it's also supported by the parent node.
|
||||
if (supportsBasicCommandClass) {
|
||||
ZWaveCommandClass commandClass = new ZWaveBasicCommandClass(this.getNode(), this.getController(), endpoint);
|
||||
endpoint.addCommandClass(commandClass);
|
||||
}
|
||||
|
||||
for (int i = 0; i < serialMessage.getMessagePayload().length - offset - 3; i++) {
|
||||
int data = serialMessage.getMessagePayloadByte(offset + 3 + i);
|
||||
if(data == 0xef ) {
|
||||
|
@ -331,8 +339,17 @@ public class ZWaveMultiInstanceCommandClass extends ZWaveCommandClass {
|
|||
}
|
||||
logger.debug(String.format("Adding command class 0x%02X to the list of supported command classes.", data));
|
||||
ZWaveCommandClass commandClass = ZWaveCommandClass.getInstance(data, this.getNode(), this.getController(), endpoint);
|
||||
if (commandClass != null)
|
||||
endpoint.addCommandClass(commandClass);
|
||||
if (commandClass == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
endpoint.addCommandClass(commandClass);
|
||||
ZWaveCommandClass parentClass = this.getNode().getCommandClass(commandClass.getCommandClass());
|
||||
|
||||
// copy version info to endpoint classes.
|
||||
if (parentClass != null) {
|
||||
commandClass.setVersion(parentClass.getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -355,6 +355,15 @@ public class ZWaveNode {
|
|||
return supportedCommandClasses.get(commandClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a node supports this command class.
|
||||
* @param commandClass the command class to check
|
||||
* @return true if the command class is supported, false otherwise.
|
||||
*/
|
||||
public boolean supportsCommandClass(CommandClass commandClass) {
|
||||
return supportedCommandClasses.containsKey(commandClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command class to the list of supported command classes by this node.
|
||||
* Does nothing if command class is already added.
|
||||
|
@ -388,6 +397,9 @@ public class ZWaveNode {
|
|||
*/
|
||||
public ZWaveCommandClass resolveCommandClass(CommandClass commandClass, int endpointId)
|
||||
{
|
||||
if (commandClass == null)
|
||||
return null;
|
||||
|
||||
ZWaveMultiInstanceCommandClass multiInstanceCommandClass = (ZWaveMultiInstanceCommandClass)supportedCommandClasses.get(CommandClass.MULTI_INSTANCE);
|
||||
|
||||
if (multiInstanceCommandClass != null && multiInstanceCommandClass.getVersion() == 2) {
|
||||
|
@ -402,9 +414,12 @@ public class ZWaveNode {
|
|||
|
||||
ZWaveCommandClass result = getCommandClass(commandClass);
|
||||
|
||||
if (result == null)
|
||||
return result;
|
||||
|
||||
if (multiInstanceCommandClass != null && multiInstanceCommandClass.getVersion() == 1 &&
|
||||
result.getInstances() < endpointId)
|
||||
return null;
|
||||
result.getInstances() >= endpointId)
|
||||
return result;
|
||||
|
||||
return endpointId == 1 ? result : null;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="lib" path="lib/httpmime-4.0.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/json_simple-1.1.jar"/>
|
||||
<classpathentry kind="lib" path="lib/dropbox-java-sdk-1.5.2.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="lib" path="/org.openhab.core.scheduler/lib/quartz-all-2.1.7.jar"/>
|
||||
<classpathentry kind="lib" path="lib/dropbox-core-sdk-1.7.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/jackson-core-2.2.2.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -30,12 +30,19 @@
|
|||
|
||||
-->
|
||||
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="org.openhab.io.dropbox">
|
||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" immediate="true" name="org.openhab.io.dropbox">
|
||||
<implementation class="org.openhab.io.dropbox.internal.DropboxSynchronizer"/>
|
||||
|
||||
<service>
|
||||
<provide interface="org.osgi.service.cm.ManagedService"/>
|
||||
<provide interface="org.openhab.io.dropbox.internal.DropboxSynchronizer"/>
|
||||
</service>
|
||||
<property name="service.pid" type="String" value="org.openhab.dropbox"/>
|
||||
|
||||
<property name="osgi.command.scope" type="String" value="dropbox"/>
|
||||
<property name="osgi.command.function">
|
||||
startAuthentication
|
||||
finishAuthentication
|
||||
</property>
|
||||
|
||||
</scr:component>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.io.dropbox</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ds.core.builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -2,7 +2,6 @@ source.. = src/main/java
|
|||
output.. = target/classes
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
OSGI-INF/,\
|
||||
lib/httpmime-4.0.3.jar,\
|
||||
lib/json_simple-1.1.jar,\
|
||||
lib/dropbox-java-sdk-1.5.2.jar
|
||||
OSGI-INF/synchronizer.xml,\
|
||||
lib/dropbox-core-sdk-1.7.3.jar,\
|
||||
lib/jackson-core-2.2.2.jar
|
||||
|
|
Двоичный файл не отображается.
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/dropbox-java-sdk-1.5.2.jar
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/dropbox-java-sdk-1.5.2.jar
Двоичный файл не отображается.
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/httpmime-4.0.3.jar
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/httpmime-4.0.3.jar
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/json_simple-1.1.jar
Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/json_simple-1.1.jar
Двоичный файл не отображается.
|
@ -43,10 +43,13 @@ public class DropboxActivator implements BundleActivator {
|
|||
|
||||
private static Logger logger = LoggerFactory.getLogger(DropboxActivator.class);
|
||||
|
||||
private static BundleContext context;
|
||||
|
||||
/**
|
||||
* Called whenever the OSGi framework starts our bundle
|
||||
*/
|
||||
public void start(BundleContext bc) throws Exception {
|
||||
context = bc;
|
||||
logger.debug("Dropbox IO Bundle has been started.");
|
||||
}
|
||||
|
||||
|
@ -54,7 +57,16 @@ public class DropboxActivator implements BundleActivator {
|
|||
* Called whenever the OSGi framework stops our bundle
|
||||
*/
|
||||
public void stop(BundleContext bc) throws Exception {
|
||||
context = null;
|
||||
logger.debug("Dropbox IO Bundle has been stopped.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bundle context of this bundle
|
||||
* @return the bundle context
|
||||
*/
|
||||
public static BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ package org.openhab.io.dropbox.internal;
|
|||
|
||||
import static org.apache.commons.lang.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang.StringUtils.substringAfter;
|
||||
import static org.quartz.JobBuilder.newJob;
|
||||
import static org.quartz.TriggerBuilder.newTrigger;
|
||||
import static org.quartz.impl.matchers.GroupMatcher.jobGroupEquals;
|
||||
|
@ -46,19 +45,21 @@ import java.util.Arrays;
|
|||
import java.util.Dictionary;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.osgi.service.cm.ConfigurationException;
|
||||
import org.osgi.service.cm.ManagedService;
|
||||
import org.quartz.CronScheduleBuilder;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.JobKey;
|
||||
|
@ -68,19 +69,16 @@ import org.quartz.impl.StdSchedulerFactory;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.dropbox.client2.DropboxAPI;
|
||||
import com.dropbox.client2.DropboxAPI.DeltaEntry;
|
||||
import com.dropbox.client2.DropboxAPI.DeltaPage;
|
||||
import com.dropbox.client2.DropboxAPI.Entry;
|
||||
import com.dropbox.client2.RESTUtility;
|
||||
import com.dropbox.client2.exception.DropboxException;
|
||||
import com.dropbox.client2.exception.DropboxUnlinkedException;
|
||||
import com.dropbox.client2.session.AccessTokenPair;
|
||||
import com.dropbox.client2.session.AppKeyPair;
|
||||
import com.dropbox.client2.session.RequestTokenPair;
|
||||
import com.dropbox.client2.session.Session.AccessType;
|
||||
import com.dropbox.client2.session.WebAuthSession;
|
||||
import com.dropbox.client2.session.WebAuthSession.WebAuthInfo;
|
||||
import com.dropbox.core.DbxAppInfo;
|
||||
import com.dropbox.core.DbxClient;
|
||||
import com.dropbox.core.DbxDelta;
|
||||
import com.dropbox.core.DbxDelta.Entry;
|
||||
import com.dropbox.core.DbxEntry;
|
||||
import com.dropbox.core.DbxEntry.WithChildren;
|
||||
import com.dropbox.core.DbxException;
|
||||
import com.dropbox.core.DbxRequestConfig;
|
||||
import com.dropbox.core.DbxWebAuthNoRedirect;
|
||||
import com.dropbox.core.DbxWriteMode;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -99,27 +97,24 @@ import com.dropbox.client2.session.WebAuthSession.WebAuthInfo;
|
|||
*/
|
||||
public class DropboxSynchronizer implements ManagedService {
|
||||
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(DropboxSynchronizer.class);
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DropboxSynchronizer.class);
|
||||
|
||||
private static final String DROPBOX_SCHEDULER_GROUP = "Dropbox";
|
||||
|
||||
private static final String FIELD_DELIMITER = "@@";
|
||||
|
||||
|
||||
private static final String LINE_DELIMITER = System.getProperty("line.separator");
|
||||
|
||||
|
||||
private static final String DELTA_CURSOR_FILE_NAME = File.separator + "deltacursor.dbx";
|
||||
|
||||
private static final String DROPBOX_ENTRIES_FILE_NAME = File.separator + "dropbox-entries.dbx";
|
||||
|
||||
private static final String AUTH_FILE_NAME = File.separator + "authfile.dbx";
|
||||
|
||||
|
||||
/** holds the id of the last synchronisation cursor. This is needed to define the delta to download from Dropbox. */
|
||||
private static String lastCursor = null;
|
||||
|
||||
private static String lastHash = null;
|
||||
|
||||
|
||||
/** the configured AppKey (optional, defaults to the official Dropbox-App key 'gbrwwfzvrw6a9uv') */
|
||||
private static String appKey = "gbrwwfzvrw6a9uv";
|
||||
|
@ -154,154 +149,90 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
/** operates the Synchronizer in fake mode which avoids up- or downloading files to and from Dropbox. This is meant as testMode for the filter settings (optional, defaults to false) */
|
||||
private static boolean fakeMode = false;
|
||||
|
||||
/** indicates whether the Dropbox authorization Thread should be interrupted or not (defaults to <code>false</code>)*/
|
||||
private static boolean authorizationThreadInterrupted = false;
|
||||
|
||||
private AccessTokenPair accessToken = null;
|
||||
|
||||
private static boolean isProperlyConfigured = false;
|
||||
|
||||
private static DropboxSynchronizer instance = null;
|
||||
|
||||
private static final DbxAppInfo appInfo =
|
||||
new DbxAppInfo(DropboxSynchronizer.appKey, DropboxSynchronizer.appSecret);
|
||||
|
||||
private final static DbxRequestConfig requestConfig =
|
||||
new DbxRequestConfig("openHAB/1.0", Locale.getDefault().toString());
|
||||
|
||||
|
||||
public void activate() {
|
||||
DropboxSynchronizer.instance = this;
|
||||
if (isProperlyConfigured) {
|
||||
cancelAllJobs();
|
||||
if (isAuthorized()) {
|
||||
scheduleJobs();
|
||||
} else {
|
||||
logger.debug("Dropbox-Bundle isn't authorized properly, so the synchronization jobs " +
|
||||
"won't be started! Please re-initiate the authorization process by restarting the " +
|
||||
"Dropbox-Bundle through OSGi console.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
logger.debug("about to shut down DropboxSynchronizer ...");
|
||||
|
||||
cancelAllJobs();
|
||||
authorizationThreadInterrupted = true;
|
||||
isProperlyConfigured = false;
|
||||
|
||||
lastCursor = null;
|
||||
lastHash = null;
|
||||
uploadFilterElements = DEFAULT_UPLOAD_FILE_FILTER;
|
||||
downloadFilterElements = DEFAULT_DOWNLOAD_FILE_FILTER;
|
||||
|
||||
DropboxSynchronizer.instance = null;
|
||||
}
|
||||
|
||||
|
||||
private boolean isAuthorized() {
|
||||
try {
|
||||
WebAuthSession authSession = getSession();
|
||||
return authSession != null;
|
||||
} catch (DropboxException de) {
|
||||
logger.debug("creating Dropbox session throws an exception", de);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new {@link WebAuthSession}. The Session is either
|
||||
* created with an {@link AccessTokenPair} restored from a previously created
|
||||
* file 'authfile.dbx' or with a new {@link AccessTokenPair} returned by
|
||||
* the manual Dropbox authorization process (via OAuth).
|
||||
*
|
||||
* @return a new {@link WebAuthSession} or <code>null</code> if the
|
||||
* authorization process couldn't be finished successfully.
|
||||
*
|
||||
* @throws DropboxException if there are technical or application level
|
||||
* errors in the Dropbox communication
|
||||
*/
|
||||
private synchronized WebAuthSession getSession() throws DropboxException {
|
||||
AppKeyPair appKeys = new AppKeyPair(DropboxSynchronizer.appKey, DropboxSynchronizer.appSecret);
|
||||
WebAuthSession session = new WebAuthSession(appKeys, AccessType.APP_FOLDER);
|
||||
|
||||
if (accessToken == null) {
|
||||
File authFile = new File(contentDir + AUTH_FILE_NAME);
|
||||
if (authFile.exists()) {
|
||||
accessToken = extractAccessTokenFrom(authFile);
|
||||
} else {
|
||||
accessToken = authorizeOpenHAB(session, authFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (accessToken != null) {
|
||||
session.setAccessTokenPair(accessToken);
|
||||
private void activateSynchronizer() {
|
||||
if (isAuthenticated()) {
|
||||
startSynchronizationJobs();
|
||||
} else {
|
||||
session = null;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the OAuth authorization process with Dropbox. The authorization
|
||||
* process is a multi step process which is described <a href="
|
||||
* https://www.dropbox.com/developers/start/authentication#android">here</a>
|
||||
* in more detail.
|
||||
*
|
||||
* @param session the party initialized {@link WebAuthSession}.
|
||||
* @param authFile the {@link File} to write an {@link AccessTokenPair} to
|
||||
*
|
||||
* @return an {@link AccessTokenPair} which might be <code>null</code>
|
||||
*
|
||||
* @throws DropboxException if there are technical or application level
|
||||
* errors in the Dropbox communication
|
||||
*/
|
||||
private AccessTokenPair authorizeOpenHAB(WebAuthSession session, File authFile) throws DropboxException {
|
||||
WebAuthInfo authInfo = session.getAuthInfo();
|
||||
RequestTokenPair requestToken = authInfo.requestTokenPair;
|
||||
|
||||
logger.info("################################################################################################");
|
||||
logger.info("# Dropbox-Integration: U S E R I N T E R A C T I O N R E Q U I R E D !!");
|
||||
logger.info("# 1. Open URL '{}'", authInfo.url);
|
||||
logger.info("# 2. Allow openHAB to access Dropbox. Note: The given URL is only valid for THE NEXT 5 MINUTES!");
|
||||
logger.info("################################################################################################");
|
||||
|
||||
authorizationThreadInterrupted = false;
|
||||
int waitedFor = 0;
|
||||
while (!authorizationThreadInterrupted) {
|
||||
try {
|
||||
int interval = 5000;
|
||||
Thread.sleep(interval);
|
||||
waitedFor += interval;
|
||||
try {
|
||||
session.retrieveWebAccessToken(requestToken);
|
||||
authorizationThreadInterrupted = true;
|
||||
} catch (DropboxUnlinkedException due) {
|
||||
// ignore this Exception since we expect it! It will occur
|
||||
// as long as the user has not allowed access to dropbox
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// if we already waited for more than five minutes we have to cancel
|
||||
// the authorization process since the token has been invalidated by
|
||||
// Dropbox meanwhile
|
||||
if (waitedFor > 300000) {
|
||||
authorizationThreadInterrupted = true;
|
||||
logger.info("Authorization timeslot is closed now! Please use OSGi "
|
||||
+ "console to restart the Dropbox-Bundle and re-initiate the authorization process!");
|
||||
startAuthentication();
|
||||
} catch (DbxException e) {
|
||||
logger.warn("Couldn't start authentication process: {}", e.getMessage());;
|
||||
}
|
||||
}
|
||||
|
||||
AccessTokenPair accessToken = session.getAccessTokenPair();
|
||||
if (!requestToken.equals(accessToken)) {
|
||||
logger.debug("Got token pair from Dropbox (key={}, secret={}) -> serialize to file for later use!", accessToken.key, accessToken.secret);
|
||||
writeLocalFile(authFile, accessToken.key + FIELD_DELIMITER + accessToken.secret);
|
||||
} else {
|
||||
logger.debug("AccessToken hasn't been updated by Dropbox. This is likely because the authorization timeslot timed out. Thus we didn't write an authfile for later use.");
|
||||
accessToken = null;
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the OAuth authorization process with Dropbox. The authorization
|
||||
* process is a multi step process which is described in the Wiki in detail.
|
||||
*
|
||||
* @throws DbxException if there are technical or application level errors
|
||||
* in the Dropbox communication
|
||||
*
|
||||
* @see <a href="http://code.google.com/p/openhab/wiki/DropboxIOBundle">openHAB Dropbox Wiki</a>
|
||||
*/
|
||||
public void startAuthentication() throws DbxException {
|
||||
DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(requestConfig, appInfo);
|
||||
String authUrl = webAuth.start();
|
||||
|
||||
logger.info("#########################################################################################");
|
||||
logger.info("# Dropbox-Integration: U S E R I N T E R A C T I O N R E Q U I R E D !!");
|
||||
logger.info("# 1. Open URL '{}'", authUrl);
|
||||
logger.info("# 2. Allow openHAB to access Dropbox");
|
||||
logger.info("# 3. Paste the authorisation code here using the command 'finishAuthentication \"<token>\"'");
|
||||
logger.info("#########################################################################################");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the OAuth authorization process by taking the given {@code token} and creating
|
||||
* an accessToken out of it. The authorization process is a multi step process which is
|
||||
* described in the Wiki in detail.
|
||||
*
|
||||
* @throws DbxException if there are technical or application level errors
|
||||
* in the Dropbox communication
|
||||
*
|
||||
* @see <a href="http://code.google.com/p/openhab/wiki/DropboxIOBundle">openHAB Dropbox Wiki</a>
|
||||
*/
|
||||
public void finishAuthentication(String code) throws DbxException {
|
||||
DbxWebAuthNoRedirect webAuth = new DbxWebAuthNoRedirect(requestConfig, appInfo);
|
||||
String accessToken = webAuth.finish(code).accessToken;
|
||||
writeAccessToken(accessToken);
|
||||
|
||||
logger.info("#########################################################################################");
|
||||
logger.info("# OAuth2 authentication flow has been finished successfully ");
|
||||
logger.info("#########################################################################################");
|
||||
|
||||
startSynchronizationJobs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synchronizes all changes from Dropbox to the local file system. Changes are
|
||||
* identified by the Dropbox delta mechanism which takes the <code>lastCursor</code>
|
||||
|
@ -313,26 +244,19 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
* Note: Since we define Dropbox as data master we do not care about local
|
||||
* changes while downloading files!
|
||||
*
|
||||
* @throws DropboxException if there are technical or application level
|
||||
* @throws DbxException if there are technical or application level
|
||||
* errors in the Dropbox communication
|
||||
* @throws IOException
|
||||
*/
|
||||
public void syncDropboxToLocal() throws DropboxException {
|
||||
public void syncDropboxToLocal(DbxClient client) throws DbxException, IOException {
|
||||
logger.debug("Started synchronization from Dropbox to local ...");
|
||||
|
||||
WebAuthSession session = getSession();
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DropboxAPI<WebAuthSession> dropbox = new DropboxAPI<WebAuthSession>(session);
|
||||
File cursorFile = new File(contentDir + DELTA_CURSOR_FILE_NAME);
|
||||
|
||||
if (lastCursor == null) {
|
||||
lastCursor = extractDeltaCursor(cursorFile);
|
||||
logger.trace("Last cursor was NULL and has now been recreated from the filesystem (file='{}', cursor='{}')", cursorFile.getAbsolutePath(), lastCursor);
|
||||
|
||||
lastCursor = readDeltaCursor();
|
||||
if (StringUtils.isBlank(lastCursor)) {
|
||||
logger.trace("Last cursor was NULL and has now been recreated from the filesystem '{}'", lastCursor);
|
||||
}
|
||||
|
||||
DeltaPage<Entry> deltaPage = dropbox.delta(lastCursor);
|
||||
DbxDelta<DbxEntry> deltaPage = client.getDelta(lastCursor);
|
||||
if (deltaPage.entries != null && deltaPage.entries.size() == 0) {
|
||||
logger.debug("There are no deltas to download from Dropbox ...");
|
||||
} else {
|
||||
|
@ -340,7 +264,7 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
logger.debug("There are '{}' deltas to process ...", deltaPage.entries.size());
|
||||
int processedDelta = 0;
|
||||
|
||||
for (DeltaEntry<Entry> entry : deltaPage.entries) {
|
||||
for (Entry<DbxEntry> entry : deltaPage.entries) {
|
||||
boolean matches = false;
|
||||
for (String filter : downloadFilterElements) {
|
||||
matches |= entry.lcPath.matches(filter);
|
||||
|
@ -348,7 +272,7 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
|
||||
if (matches) {
|
||||
if (entry.metadata != null) {
|
||||
downloadFile(dropbox, entry);
|
||||
downloadFile(client, entry);
|
||||
} else {
|
||||
String fqPath = contentDir + entry.lcPath;
|
||||
deleteLocalFile(fqPath);
|
||||
|
@ -361,11 +285,11 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
logger.debug("'{}' deltas met the given downloadFilter {}", processedDelta, downloadFilterElements);
|
||||
|
||||
// query again to check if there more entries to process!
|
||||
deltaPage = dropbox.delta(lastCursor);
|
||||
deltaPage = client.getDelta(lastCursor);
|
||||
} while (deltaPage.hasMore);
|
||||
}
|
||||
|
||||
writeLastCursorFile(deltaPage, cursorFile);
|
||||
writeDeltaCursor(deltaPage.cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -374,24 +298,19 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
* are less files locally the additional files will be deleted from the
|
||||
* Dropbox. New files will be uploaded or overwritten if they exist already.
|
||||
*
|
||||
* @throws DropboxException if there are technical or application level
|
||||
* @throws DbxException if there are technical or application level
|
||||
* errors in the Dropbox communication
|
||||
* @throws IOException
|
||||
*/
|
||||
public void syncLocalToDropbox() throws DropboxException {
|
||||
public void syncLocalToDropbox(DbxClient client) throws DbxException, IOException {
|
||||
logger.debug("Started synchronization from local to Dropbox ...");
|
||||
|
||||
WebAuthSession session = getSession();
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DropboxAPI<WebAuthSession> dropbox = new DropboxAPI<WebAuthSession>(session);
|
||||
Map<String, Long> dropboxEntries = new HashMap<String, Long>();
|
||||
|
||||
Entry metadata = dropbox.metadata("/", -1, null, true, null);
|
||||
WithChildren metadata = client.getMetadataWithChildren("/");
|
||||
File dropboxEntryFile = new File(contentDir + DROPBOX_ENTRIES_FILE_NAME);
|
||||
if (!dropboxEntryFile.exists() || !metadata.hash.equals(lastHash)) {
|
||||
collectDropboxEntries(dropbox, dropboxEntries, "/");
|
||||
collectDropboxEntries(client, dropboxEntries, "/");
|
||||
serializeDropboxEntries(dropboxEntryFile, dropboxEntries);
|
||||
lastHash = metadata.hash;
|
||||
|
||||
|
@ -413,14 +332,14 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
if (entry.getValue().compareTo(dropboxEntries.get(entry.getKey())) > 0) {
|
||||
logger.trace("Local file '{}' is newer - upload to Dropbox!", entry.getKey());
|
||||
if (!fakeMode) {
|
||||
uploadOverwriteFile(dropbox, entry.getKey());
|
||||
uploadFile(client, entry.getKey(), true);
|
||||
}
|
||||
isChanged = true;
|
||||
}
|
||||
} else {
|
||||
logger.trace("Local file '{}' doesn't exist in Dropbox - upload to Dropbox!", entry.getKey());
|
||||
if (!fakeMode) {
|
||||
uploadFile(dropbox, entry.getKey());
|
||||
uploadFile(client, entry.getKey(), false);
|
||||
}
|
||||
isChanged = true;
|
||||
}
|
||||
|
@ -434,7 +353,7 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
for (String filter : uploadFilterElements) {
|
||||
if (path.matches(filter)) {
|
||||
if (!fakeMode) {
|
||||
dropbox.delete(path);
|
||||
client.delete(path);
|
||||
}
|
||||
isChanged = true;
|
||||
logger.debug("Successfully deleted file '{}' from Dropbox", path);
|
||||
|
@ -457,51 +376,19 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
// since there are changes we have to update the lastCursor (and
|
||||
// the corresponding file) to have the right starting point for the
|
||||
// next synchronization loop
|
||||
DeltaPage<Entry> deltaPage = dropbox.delta(lastCursor);
|
||||
writeLastCursorFile(deltaPage, new File(contentDir + DELTA_CURSOR_FILE_NAME));
|
||||
DbxDelta<DbxEntry> delta = client.getDelta(lastCursor);
|
||||
writeDeltaCursor(delta.cursor);
|
||||
} else {
|
||||
logger.debug("No files changed locally > no deltas to upload to Dropbox ...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static AccessTokenPair extractAccessTokenFrom(File authFile) {
|
||||
AccessTokenPair tokenPair = null;
|
||||
try {
|
||||
List<String> lines = FileUtils.readLines(authFile);
|
||||
if (lines.size() > 0) {
|
||||
String line = lines.get(0);
|
||||
String[] tokenPairArray = line.split(FIELD_DELIMITER);
|
||||
if (tokenPairArray.length == 2) {
|
||||
tokenPair = new AccessTokenPair(tokenPairArray[0], tokenPairArray[1]);
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
logger.debug("Handling of authentication file throws an Exception", ioe);
|
||||
}
|
||||
return tokenPair;
|
||||
}
|
||||
|
||||
private String extractDeltaCursor(File cursorFile) {
|
||||
String cursor = null;
|
||||
if (cursorFile.exists()) {
|
||||
try {
|
||||
List<String> lines = FileUtils.readLines(cursorFile);
|
||||
if (lines.size() > 0) {
|
||||
cursor = lines.get(0);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
logger.debug("Handling of cursor file throws an Exception", ioe);
|
||||
}
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
private void downloadFile(DropboxAPI<WebAuthSession> dropbox, DeltaEntry<Entry> entry) throws DropboxException {
|
||||
private void downloadFile(DbxClient client, Entry<DbxEntry> entry) throws DbxException, IOException {
|
||||
String fqPath = contentDir + entry.metadata.path;
|
||||
File newLocalFile = new File(fqPath);
|
||||
|
||||
if (entry.metadata.isDir) {
|
||||
if (entry.metadata.isFolder()) {
|
||||
// create intermediary directories
|
||||
boolean success = newLocalFile.mkdirs();
|
||||
if (!success) {
|
||||
|
@ -517,19 +404,19 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
try {
|
||||
FileOutputStream os = new FileOutputStream(newLocalFile);
|
||||
if (!fakeMode) {
|
||||
dropbox.getFile(entry.metadata.path, null, os, null);
|
||||
client.getFile(entry.metadata.path, null, os);
|
||||
}
|
||||
logger.debug("Successfully downloaded file '{}'", fqPath);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
throw new DropboxException("Couldn't write file '" + fqPath + "'", fnfe);
|
||||
throw new DbxException("Couldn't write file '" + fqPath + "'", fnfe);
|
||||
}
|
||||
|
||||
long lastModified = entry.metadata.asFile().lastModified.getTime();
|
||||
boolean success = newLocalFile.setLastModified(lastModified);
|
||||
if (!success) {
|
||||
logger.debug("Couldn't change attribute 'lastModified' of file '{}'", fqPath);
|
||||
}
|
||||
}
|
||||
|
||||
long lastModified = RESTUtility.parseDate(entry.metadata.modified).getTime();
|
||||
boolean success = newLocalFile.setLastModified(lastModified);
|
||||
if (!success) {
|
||||
logger.debug("Couldn't change attribute 'lastModified' of file '{}'", fqPath);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Long> extractDropboxEntries(File dropboxEntryFile) {
|
||||
|
@ -566,7 +453,7 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
File[] files = new File(path).listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
String normalizedPath = substringAfter(file.getPath(), contentDir);
|
||||
String normalizedPath = StringUtils.substringAfter(file.getPath(), contentDir);
|
||||
for (String filter : uploadFilterElements) {
|
||||
if (FilenameUtils.getName(normalizedPath).startsWith(".")) {
|
||||
return false;
|
||||
|
@ -583,7 +470,7 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
});
|
||||
|
||||
for (File file : files) {
|
||||
String normalizedPath = substringAfter(file.getPath(), contentDir);
|
||||
String normalizedPath = StringUtils.substringAfter(file.getPath(), contentDir);
|
||||
if (file.isDirectory()) {
|
||||
collectLocalEntries(localEntries, file.getPath());
|
||||
} else {
|
||||
|
@ -592,13 +479,13 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
}
|
||||
}
|
||||
|
||||
private void collectDropboxEntries(DropboxAPI<WebAuthSession> dropbox, Map<String, Long> dropboxEntries, String path) throws DropboxException {
|
||||
Entry entries = dropbox.metadata(path, -1 /* unlimited */, null, true /* children */, null /* latest */);
|
||||
for (Entry entry : entries.contents) {
|
||||
if (entry.isDir) {
|
||||
collectDropboxEntries(dropbox, dropboxEntries, entry.path);
|
||||
private void collectDropboxEntries(DbxClient client, Map<String, Long> dropboxEntries, String path) throws DbxException {
|
||||
WithChildren entries = client.getMetadataWithChildren(path);
|
||||
for (DbxEntry entry : entries.children) {
|
||||
if (entry.isFolder()) {
|
||||
collectDropboxEntries(client, dropboxEntries, entry.path);
|
||||
} else {
|
||||
dropboxEntries.put(entry.path, RESTUtility.parseDate(entry.modified).getTime());
|
||||
dropboxEntries.put(entry.path, entry.asFile().lastModified.getTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -613,43 +500,60 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
*
|
||||
* @see http://forums.dropbox.com/topic.php?id=22347
|
||||
*/
|
||||
private void uploadFile(DropboxAPI<WebAuthSession> dropbox, String dropboxPath) throws DropboxException {
|
||||
try {
|
||||
File file = new File(contentDir + File.separator + dropboxPath);
|
||||
Entry newEntry = dropbox.putFile(dropboxPath, new FileInputStream(file), file.length(), null, null);
|
||||
logger.debug("successfully uploaded file '{}'. New revision is '{}'", file.getPath(), newEntry.rev);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
logger.error("Errors while uploading file '" + dropboxPath + "'", fnfe);
|
||||
private void uploadFile(DbxClient client, String dropboxPath, boolean overwrite) throws DbxException, IOException {
|
||||
File file = new File(contentDir + File.separator + dropboxPath);
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
try {
|
||||
DbxWriteMode mode = overwrite ? DbxWriteMode.force() : DbxWriteMode.add();
|
||||
DbxEntry.File uploadedFile =
|
||||
client.uploadFile(dropboxPath, mode, file.length(), inputStream);
|
||||
logger.debug("successfully uploaded file '{}'. New revision is '{}'", uploadedFile.toString(), uploadedFile.rev);
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAccessToken(String content) {
|
||||
File tokenFile = new File(contentDir + AUTH_FILE_NAME);
|
||||
writeLocalFile(tokenFile, content);
|
||||
}
|
||||
|
||||
private String readAccessToken() {
|
||||
File tokenFile = new File(contentDir + AUTH_FILE_NAME);
|
||||
return readFile(tokenFile);
|
||||
}
|
||||
|
||||
private boolean isAuthenticated() {
|
||||
return StringUtils.isNotBlank(readAccessToken());
|
||||
}
|
||||
|
||||
private void writeDeltaCursor(String deltaCursor) {
|
||||
if (!deltaCursor.equals(lastCursor)) {
|
||||
logger.trace("Delta-Cursor changed (lastCursor '{}', newCursor '{}')", lastCursor, deltaCursor);
|
||||
File cursorFile = new File(contentDir + DELTA_CURSOR_FILE_NAME);
|
||||
writeLocalFile(cursorFile, deltaCursor);
|
||||
lastCursor = deltaCursor;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: TEE: Currently there is now way to change the attribute
|
||||
* 'lastModified' of the files to upload via Dropbox API. See the
|
||||
* discussion below for more details.
|
||||
*
|
||||
* Since this is a missing feature (from my point of view) we should
|
||||
* check the improvements of the API development on regular basis.
|
||||
*
|
||||
* @see http://forums.dropbox.com/topic.php?id=22347
|
||||
*/
|
||||
private void uploadOverwriteFile(DropboxAPI<WebAuthSession> dropbox, String dropboxPath) throws DropboxException {
|
||||
try {
|
||||
File file = new File(contentDir + File.separator + dropboxPath);
|
||||
Entry newEntry = dropbox.putFileOverwrite(dropboxPath, new FileInputStream(file), file.length(), null);
|
||||
logger.debug("successfully overwritten file '{}'. New revision is '{}'", file.getPath(), newEntry.rev);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
logger.error("Errors while uploading file '" + dropboxPath + "'", fnfe);
|
||||
}
|
||||
private String readDeltaCursor() {
|
||||
File cursorFile = new File(contentDir + DELTA_CURSOR_FILE_NAME);
|
||||
return readFile(cursorFile);
|
||||
}
|
||||
|
||||
private static void writeLastCursorFile(DeltaPage<Entry> deltaPage, File cursorFile) {
|
||||
String newCursor = deltaPage.cursor;
|
||||
if (!newCursor.equals(lastCursor)) {
|
||||
logger.trace("Delta-Cursor changed (lastCursor '{}', newCursor '{}')", lastCursor, newCursor);
|
||||
writeLocalFile(cursorFile, newCursor);
|
||||
lastCursor = newCursor;
|
||||
|
||||
private String readFile(File file) {
|
||||
String content = null;
|
||||
if (file.exists()) {
|
||||
try {
|
||||
List<String> lines = FileUtils.readLines(file);
|
||||
if (lines.size() > 0) {
|
||||
content = lines.get(0);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
logger.debug("Handling of cursor file throws an Exception", ioe);
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private static void writeLocalFile(File file, String content) {
|
||||
|
@ -678,70 +582,6 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
logger.trace("Local file '{}' isn't deleted because it is a directory");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the quartz synchronization according to the synchronization mode
|
||||
*/
|
||||
private void scheduleJobs() {
|
||||
switch (syncMode) {
|
||||
case DROPBOX_TO_LOCAL:
|
||||
schedule(DropboxSynchronizer.downloadInterval, false);
|
||||
break;
|
||||
case LOCAL_TO_DROPBOX:
|
||||
schedule(DropboxSynchronizer.uploadInterval, true);
|
||||
break;
|
||||
case BIDIRECTIONAL:
|
||||
schedule(DropboxSynchronizer.downloadInterval, false);
|
||||
schedule(DropboxSynchronizer.uploadInterval, true);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown SyncMode '" + syncMode.toString() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules either a job handling the Upload (<code>LOCAL_TO_DROPBOX</code>)
|
||||
* or Download (<code>DROPBOX_TO_LOCAL</code>) direction depending on
|
||||
* <code>isUpload</code>.
|
||||
*
|
||||
* @param interval the Trigger interval as cron expression
|
||||
* @param isUpload
|
||||
*/
|
||||
private void schedule(String interval, boolean isUpload) {
|
||||
String direction = isUpload ? "Upload" : "Download";
|
||||
try {
|
||||
Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
|
||||
JobDetail job = newJob(SynchronizationJob.class)
|
||||
.withIdentity(direction, DROPBOX_SCHEDULER_GROUP)
|
||||
.build();
|
||||
|
||||
CronTrigger trigger = newTrigger()
|
||||
.withIdentity(direction, DROPBOX_SCHEDULER_GROUP)
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(interval))
|
||||
.build();
|
||||
|
||||
sched.scheduleJob(job, trigger);
|
||||
logger.debug("Scheduled synchronization job (direction={}) with cron expression '{}'", direction, interval);
|
||||
} catch (SchedulerException e) {
|
||||
logger.warn("Could not create synchronization job: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all quartz scheduler jobs of the group <code>Dropbox</code>.
|
||||
*/
|
||||
private void cancelAllJobs() {
|
||||
try {
|
||||
Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
|
||||
Set<JobKey> jobKeys = sched.getJobKeys(jobGroupEquals(DROPBOX_SCHEDULER_GROUP));
|
||||
if (jobKeys.size() > 0) {
|
||||
sched.deleteJobs(new ArrayList<JobKey>(jobKeys));
|
||||
logger.debug("Found {} synchronization jobs to delete from DefaulScheduler (keys={})", jobKeys.size(), jobKeys);
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.warn("Couldn't remove synchronization job: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -810,11 +650,92 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
|
||||
// we got thus far, so we define this synchronizer as properly configured ...
|
||||
isProperlyConfigured = true;
|
||||
activate();
|
||||
activateSynchronizer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// Synchronisation Jobs
|
||||
// ****************************************************************************
|
||||
|
||||
private void startSynchronizationJobs() {
|
||||
if (isProperlyConfigured) {
|
||||
cancelAllJobs();
|
||||
if (isAuthenticated()) {
|
||||
scheduleJobs();
|
||||
} else {
|
||||
logger.debug("Dropbox-Bundle isn't authorized properly, so the synchronization jobs " +
|
||||
"won't be started! Please re-initiate the authorization process by restarting the " +
|
||||
"Dropbox-Bundle through OSGi console.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the quartz synchronization according to the synchronization mode
|
||||
*/
|
||||
private void scheduleJobs() {
|
||||
switch (syncMode) {
|
||||
case DROPBOX_TO_LOCAL:
|
||||
schedule(DropboxSynchronizer.downloadInterval, false);
|
||||
break;
|
||||
case LOCAL_TO_DROPBOX:
|
||||
schedule(DropboxSynchronizer.uploadInterval, true);
|
||||
break;
|
||||
case BIDIRECTIONAL:
|
||||
schedule(DropboxSynchronizer.downloadInterval, false);
|
||||
schedule(DropboxSynchronizer.uploadInterval, true);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown SyncMode '" + syncMode.toString() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules either a job handling the Upload (<code>LOCAL_TO_DROPBOX</code>)
|
||||
* or Download (<code>DROPBOX_TO_LOCAL</code>) direction depending on
|
||||
* <code>isUpload</code>.
|
||||
*
|
||||
* @param interval the Trigger interval as cron expression
|
||||
* @param isUpload
|
||||
*/
|
||||
private void schedule(String interval, boolean isUpload) {
|
||||
String direction = isUpload ? "Upload" : "Download";
|
||||
try {
|
||||
Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
|
||||
JobDetail job = newJob(SynchronizationJob.class)
|
||||
.withIdentity(direction, DROPBOX_SCHEDULER_GROUP)
|
||||
.build();
|
||||
|
||||
CronTrigger trigger = newTrigger()
|
||||
.withIdentity(direction, DROPBOX_SCHEDULER_GROUP)
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(interval))
|
||||
.build();
|
||||
|
||||
sched.scheduleJob(job, trigger);
|
||||
logger.debug("Scheduled synchronization job (direction={}) with cron expression '{}'", direction, interval);
|
||||
} catch (SchedulerException e) {
|
||||
logger.warn("Could not create synchronization job: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all quartz scheduler jobs of the group <code>Dropbox</code>.
|
||||
*/
|
||||
private void cancelAllJobs() {
|
||||
try {
|
||||
Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
|
||||
Set<JobKey> jobKeys = sched.getJobKeys(jobGroupEquals(DROPBOX_SCHEDULER_GROUP));
|
||||
if (jobKeys.size() > 0) {
|
||||
sched.deleteJobs(new ArrayList<JobKey>(jobKeys));
|
||||
logger.debug("Found {} synchronization jobs to delete from DefaulScheduler (keys={})", jobKeys.size(), jobKeys);
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.warn("Couldn't remove synchronization job: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A quartz scheduler job to execute the synchronization. There can be only
|
||||
* one instance of a specific job type running at the same time.
|
||||
|
@ -829,23 +750,44 @@ public class DropboxSynchronizer implements ManagedService {
|
|||
boolean isUpload =
|
||||
UPLOAD_JOB_KEY.compareTo(context.getJobDetail().getKey()) == 0;
|
||||
|
||||
try {
|
||||
DropboxSynchronizer synchronizer = DropboxSynchronizer.instance;
|
||||
if (synchronizer != null) {
|
||||
if (isUpload) {
|
||||
synchronizer.syncLocalToDropbox();
|
||||
DropboxSynchronizer synchronizer = DropboxSynchronizer.instance;
|
||||
if (synchronizer != null) {
|
||||
try {
|
||||
DbxClient client = getClient(synchronizer);
|
||||
if (client != null) {
|
||||
if (isUpload) {
|
||||
synchronizer.syncLocalToDropbox(client);
|
||||
} else {
|
||||
synchronizer.syncDropboxToLocal(client);
|
||||
}
|
||||
} else {
|
||||
synchronizer.syncDropboxToLocal();
|
||||
logger.info("Couldn't create Dropbox client. Most likely there has been no "
|
||||
+ "access token found. Please restart authentication process by typing "
|
||||
+ "'startAuthentication' on the OSGi console");
|
||||
}
|
||||
} else {
|
||||
logger.debug("DropboxSynchronizer instance hasn't been initialized properly!");
|
||||
} catch (Exception e) {
|
||||
logger.warn("Synchronizing data with Dropbox throws an exception: {}", e.getMessage());
|
||||
}
|
||||
} catch (DropboxException de) {
|
||||
logger.error("Synchronization files with Dropbox throws an exception", de);
|
||||
} else {
|
||||
logger.debug("DropboxSynchronizer instance hasn't been initialized properly!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new {@link DbxClient} initialized with the store access token.
|
||||
* Returns {@code null} if no access token has been found.
|
||||
*
|
||||
* @return a new {@link DbxClient} or <code>null</code> if no access token has been found.
|
||||
*/
|
||||
private DbxClient getClient(DropboxSynchronizer synchronizer) {
|
||||
String accessToken = synchronizer.readAccessToken();
|
||||
if (StringUtils.isNotBlank(accessToken)) {
|
||||
return new DbxClient(requestConfig, accessToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -335,14 +335,18 @@ public class SitemapResource {
|
|||
if(widget instanceof Image) {
|
||||
Image imageWidget = (Image) widget;
|
||||
String wId = itemUIRegistry.getWidgetId(widget);
|
||||
bean.url = uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + "/proxy?sitemap=" + sitemapName + ".sitemap&widgetId=" + wId;
|
||||
String host = uri.getHost();
|
||||
int port = uri.getPort();
|
||||
bean.url = uri.getScheme() + "://" + host + (port!=-1 ? ":" + port : "") + "/proxy?sitemap=" + sitemapName + ".sitemap&widgetId=" + wId;
|
||||
if(imageWidget.getRefresh()>0) {
|
||||
bean.refresh = imageWidget.getRefresh();
|
||||
}
|
||||
}
|
||||
if(widget instanceof Video) {
|
||||
String wId = itemUIRegistry.getWidgetId(widget);
|
||||
bean.url = uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort() + "/proxy?sitemap=" + sitemapName + ".sitemap&widgetId=" + wId;
|
||||
String host = uri.getHost();
|
||||
int port = uri.getPort();
|
||||
bean.url = uri.getScheme() + "://" + host + (port!=-1 ? ":" + port : "") + "/proxy?sitemap=" + sitemapName + ".sitemap&widgetId=" + wId;
|
||||
}
|
||||
if(widget instanceof Webview) {
|
||||
Webview webViewWidget = (Webview) widget;
|
||||
|
|
|
@ -114,6 +114,7 @@ public class ModelRepositoryImpl implements ModelRepository {
|
|||
synchronized(resourceSet) {
|
||||
resource.unload();
|
||||
try {
|
||||
logger.info("Refreshing model '{}'", name);
|
||||
resource.load(inputStream, Collections.EMPTY_MAP);
|
||||
notifyListeners(name, EventType.MODIFIED);
|
||||
return true;
|
||||
|
|
|
@ -143,7 +143,7 @@ public class GenericItemProvider implements ItemProvider, ModelRepositoryChangeL
|
|||
*/
|
||||
@Override
|
||||
public Collection<Item> getItems() {
|
||||
Set<Item> items = new HashSet<Item>();
|
||||
List<Item> items = new ArrayList<Item>();
|
||||
for (String name : modelRepository.getAllModelNamesOfType("items")) {
|
||||
items.addAll(getItemsFromModel(name));
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ Group FF_Bed "Bedroom" <bedroom> (gFF)
|
|||
Group FF_Corridor "Corridor" <corridor> (gFF)
|
||||
|
||||
/* active groups */
|
||||
Group:Number:SUM Lights "All Lights [(%d)]" (All)
|
||||
Group:Switch:OR(ON, OFF) Lights "All Lights [(%d)]" (All)
|
||||
Group:Switch:OR(ON, OFF) Heating "No. of Active Heatings [(%d)]" <heating> (All)
|
||||
Group:Number:AVG Temperature "Avg. Room Temperature [%.1f °C]" <temperature> (Status)
|
||||
Group:Contact:OR(OPEN, CLOSED) Windows "Open windows [(%d)]" <contact> (All)
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<include>org.openhab.persistence:*:jar:*</include>
|
||||
<include>org.openhab.io:org.openhab.io.multimedia.tts.freetts:jar:*</include>
|
||||
<include>org.openhab.io:org.openhab.io.multimedia.tts.marytts:jar:*</include>
|
||||
<!--<include>org.openhab.io:org.openhab.io.dropbox:jar:*</include>-->
|
||||
<include>org.openhab.io:org.openhab.io.dropbox:jar:*</include>
|
||||
</includes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
|
|
Загрузка…
Ссылка в новой задаче