Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[homekit] bugfix 7701. add delay on homekit bridge start in case of configuration diffs #7725

Merged
merged 2 commits into from
May 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bundles/org.openhab.io.homekit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ org.openhab.homekit:maximumTemperature=100
| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the first network adapter address. | (none) |
| port | Port under which the HomeKit bridge can be reached. | 9123 |
| pin | Pin code used for pairing with iOS devices. Apparently, pin codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The pin code 031-45-154 is used in sample applications and known to work. | 031-45-154 |
| startDelay | HomeKit start delay in seconds in case the number of accessories is lower than last time. This helps to avoid resetting home app in case not all items have been initialised properly before HomeKit integration start. | 30 |
| useFahrenheitTemperature | Set to true to use Fahrenheit degrees, or false to use Celsius degrees. | false |
| thermostatTargetModeCool | Word used for activating the cooling mode of the device (if applicable). | CoolOn |
| thermostatTargetModeHeat | Word used for activating the heating mode of the device (if applicable). | HeatOn |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@
public class HomekitChangeListener implements ItemRegistryChangeListener {
private final Logger logger = LoggerFactory.getLogger(HomekitChangeListener.class);
private final static String REVISION_CONFIG = "revision";
private final static String ACCESSORY_COUNT = "accessory_count";
private final ItemRegistry itemRegistry;
private final HomekitAccessoryRegistry accessoryRegistry = new HomekitAccessoryRegistry();
private final MetadataRegistry metadataRegistry;
private final Storage<String> storage;
private HomekitAccessoryUpdater updater = new HomekitAccessoryUpdater();
private HomekitSettings settings;
private int lastAccessoryCount;

private Set<String> pendingUpdates = new HashSet<>();

Expand All @@ -79,13 +81,12 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
this.settings = settings;
this.metadataRegistry = metadataRegistry;
storage = storageService.getStorage("homekit");
initialiseRevision();

this.applyUpdatesDebouncer = new Debouncer("update-homekit-devices", scheduler, Duration.ofMillis(1000),
Clock.systemUTC(), this::applyUpdates);

itemRegistry.addRegistryChangeListener(this);
itemRegistry.getItems().stream().forEach(this::createRootAccessories);
initialiseRevision();
logger.info("Created {} HomeKit items.", accessoryRegistry.getAllAccessories().size());
}

Expand All @@ -97,6 +98,12 @@ private void initialiseRevision() {
revision = 1;
storage.put(REVISION_CONFIG, "" + revision);
}
try {
lastAccessoryCount = Integer.valueOf(storage.get(ACCESSORY_COUNT));
} catch (java.lang.NumberFormatException e) {
lastAccessoryCount = 0;
storage.put(ACCESSORY_COUNT, "" + accessoryRegistry.getAllAccessories().size());
}
accessoryRegistry.setConfigurationRevision(revision);
}

Expand Down Expand Up @@ -143,6 +150,12 @@ private Optional<Item> getItemOptional(String name) {
}
}

public void makeNewConfigurationRevision() {
storage.put(REVISION_CONFIG, "" + accessoryRegistry.makeNewConfigurationRevision());
lastAccessoryCount = accessoryRegistry.getAllAccessories().size();
storage.put(ACCESSORY_COUNT, "" + lastAccessoryCount);
}

private synchronized void applyUpdates() {
logger.trace("apply updates");
Iterator<String> iter = pendingUpdates.iterator();
Expand All @@ -154,7 +167,7 @@ private synchronized void applyUpdates() {
getItemOptional(name).ifPresent(this::createRootAccessories);
}
if (!pendingUpdates.isEmpty()) {
storage.put(REVISION_CONFIG, "" + accessoryRegistry.makeNewConfigurationRevision());
makeNewConfigurationRevision();
pendingUpdates.clear();
}
}
Expand All @@ -165,6 +178,10 @@ public void updated(Item oldElement, Item element) {
markDirty(element);
}

public int getLastAccessoryCount() {
return lastAccessoryCount;
}

public synchronized void clearAccessories() {
accessoryRegistry.clear();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.ConfigurableService;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.common.ThreadPoolManager;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.items.MetadataRegistry;
import org.eclipse.smarthome.core.net.NetworkAddressService;
Expand Down Expand Up @@ -66,6 +69,9 @@ public class HomekitImpl implements Homekit {
private @Nullable HomekitServer homekitServer;
private @Nullable HomekitRoot bridge;

private final ScheduledExecutorService scheduler = ThreadPoolManager
.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON);

@Activate
public HomekitImpl(@Reference StorageService storageService, @Reference ItemRegistry itemRegistry,
@Reference NetworkAddressService networkAddressService, Map<String, Object> config,
Expand Down Expand Up @@ -120,13 +126,29 @@ private void startBridge() throws InvalidAlgorithmParameterException, IOExceptio
final HomekitServer homekitServer = this.homekitServer;
if (homekitServer != null && bridge == null) {
final HomekitRoot bridge = homekitServer.createBridge(new HomekitAuthInfoImpl(storageService, settings.pin),
settings.name, HomekitSettings.MANUFACTURER,
FrameworkUtil.getBundle(getClass()).getVersion().toString(), HomekitSettings.SERIAL_NUMBER,
HomekitSettings.FIRMWARE_REVISION, HomekitSettings.HARDWARE_REVISION);
settings.name, HomekitSettings.MANUFACTURER, HomekitSettings.MODEL, HomekitSettings.SERIAL_NUMBER,
FrameworkUtil.getBundle(getClass()).getVersion().toString(), HomekitSettings.HARDWARE_REVISION);
changeListener.setBridge(bridge);
bridge.setConfigurationIndex(changeListener.getConfigurationRevision());
bridge.start();
this.bridge = bridge;
bridge.setConfigurationIndex(changeListener.getConfigurationRevision());

final int lastAccessoryCount = changeListener.getLastAccessoryCount();
int currentAccessoryCount = changeListener.getAccessories().size();
if (currentAccessoryCount < lastAccessoryCount) {
logger.debug(
"It looks like not all items were initialized yet. Old configuration had {} accessories, the current one has only {} accessories. Delay HomeKit bridge start for {} seconds.",
lastAccessoryCount, currentAccessoryCount, settings.startDelay);
scheduler.schedule(() -> {
if (currentAccessoryCount < lastAccessoryCount) {
// the number of items is still different, maybe it is desired.
// make new configuration revision.
changeListener.makeNewConfigurationRevision();
}
bridge.start();
}, settings.startDelay, TimeUnit.SECONDS);
} else { // start bridge immediately.
bridge.start();
}
} else {
logger.warn(
"trying to start bridge but HomeKit server is not initialized or bridge is already initialized");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
* @author Andy Lintner - Initial contribution
*/
public class HomekitSettings {
public static final String MANUFACTURER = "openHAB";
public static final String MANUFACTURER = "openHAB Community";
public static final String SERIAL_NUMBER = "none";
public static final String FIRMWARE_REVISION = "2.5.3";
public static final String MODEL = "openHAB";
public static final String HARDWARE_REVISION = "2.5";

public String name = "openHAB";
public int port = 9123;
public String pin = "031-45-154";
public int startDelay = 30;
public boolean useFahrenheitTemperature = false;
public double minimumTemperature = -100;
public double maximumTemperature = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@
<label>Network Interface</label>
<description>Defines the IP address of the network interface to expose the HomeKit integration on.</description>
</parameter>

<parameter name="startDelay" type="integer" required="true" groupName="core" unit="s">
<label>Start Delay</label>
<description>HomeKit start delay in case of item configuration differences.</description>
<default>30</default>
</parameter>
<parameter name="useFahrenheitTemperature" type="boolean" required="true" groupName="thermostat">
<label>Use Fahrenheit Temperature</label>
<description>Defines whether or not to direct HomeKit clients to use fahrenheit temperatures instead of celsius.</description>
Expand Down