Merge 1.3.1 into default (which is 1.4 now)

This commit is contained in:
teichsta 2013-09-20 00:17:33 +02:00
Родитель b81e8fe998 fe2cf0431c
Коммит b1677d05b6
58 изменённых файлов: 3136 добавлений и 4094 удалений

Просмотреть файл

@ -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-core-sdk-1.7.3.jar Normal file

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичные данные
bundles/io/org.openhab.io.dropbox/lib/jackson-core-2.2.2.jar Normal file

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

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