[homekit] allow multiple bridge instances to break the 150 limit (#13226)
fixes #11508, #12927 Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
parent
b075d3781c
commit
e4c9a40d03
@ -97,6 +97,7 @@ org.openhab.homekit:networkInterface=192.168.0.6
|
||||
org.openhab.homekit:useOHmDNS=false
|
||||
org.openhab.homekit:blockUserDeletion=false
|
||||
org.openhab.homekit:name=openHAB
|
||||
org.openhab.homekit:instances=1
|
||||
```
|
||||
|
||||
### Overview of all settings
|
||||
@ -115,6 +116,7 @@ org.openhab.homekit:name=openHAB
|
||||
| thermostatTargetModeAuto | Word used for activating the automatic mode of the device (if applicable). It can be overwritten at item level. | Auto |
|
||||
| thermostatTargetModeOff | Word used to set the thermostat mode of the device to off (if applicable). It can be overwritten at item level. | Off |
|
||||
| name | Name under which this HomeKit bridge is announced on the network. This is also the name displayed on the iOS device when searching for available bridges. | openHAB |
|
||||
| instances | Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be assigned to additional instances via metadata. Additional bridges will use incrementing port numbers. | 1 |
|
||||
|
||||
## Item Configuration
|
||||
|
||||
@ -836,6 +838,29 @@ Number cooler_cool_thrs "Cooler Cool Threshold Temp [%.1f °C
|
||||
Number cooler_heat_thrs "Cooler Heat Threshold Temp [%.1f °C]" (gCooler) {homekit="HeatingThresholdTemperature" [minValue=0.5, maxValue=20]}
|
||||
```
|
||||
|
||||
## Multiple Instances
|
||||
|
||||
Homekit has a limitation of 150 accessories per bridge.
|
||||
The bridge itself counts as an accessory, so in practice it's 149.
|
||||
In order to overcome this limitation, you can instruct OpenHAB to expose multiple bridges to Homekit, and then manually assign specific accessories to different instances.
|
||||
You will need to manually add each additional bridge in the Home app, since the QR Code in settings will only be for the primary bridge; however the same PIN is still used.
|
||||
In order to assign a particular accessory to a different bridge, set the `instance` metadata parameter:
|
||||
|
||||
```
|
||||
Switch kitchen_light {homekit="Lighting" [instance=2]}
|
||||
```
|
||||
|
||||
Note that instances are numbered starting at 1.
|
||||
If you reference an instance that doesn't exist, then that accessory won't be exposed on _any_ bridge.
|
||||
|
||||
For complex items, only the root group needs to be tagged for the specific instance:
|
||||
|
||||
```
|
||||
Group gSecuritySystem "Security System Group" {homekit="SecuritySystem" [instance=2]}
|
||||
String security_current_state "Security Current State" (gSecuritySystem) {homekit="SecuritySystem.CurrentSecuritySystemState"}
|
||||
String security_target_state "Security Target State" (gSecuritySystem) {homekit="SecuritySystem.TargetSecuritySystemState"}
|
||||
```
|
||||
|
||||
## Additional Notes
|
||||
|
||||
HomeKit allows only a single pairing to be established with the bridge.
|
||||
|
||||
@ -62,6 +62,7 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
private HomekitAccessoryUpdater updater = new HomekitAccessoryUpdater();
|
||||
private HomekitSettings settings;
|
||||
private int lastAccessoryCount;
|
||||
private int instance;
|
||||
|
||||
private final Set<String> pendingUpdates = new HashSet<>();
|
||||
|
||||
@ -79,11 +80,12 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
private final Debouncer applyUpdatesDebouncer;
|
||||
|
||||
HomekitChangeListener(ItemRegistry itemRegistry, HomekitSettings settings, MetadataRegistry metadataRegistry,
|
||||
Storage<String> storage) {
|
||||
Storage<String> storage, int instance) {
|
||||
this.itemRegistry = itemRegistry;
|
||||
this.settings = settings;
|
||||
this.metadataRegistry = metadataRegistry;
|
||||
this.storage = storage;
|
||||
this.instance = instance;
|
||||
this.applyUpdatesDebouncer = new Debouncer("update-homekit-devices", scheduler, Duration.ofMillis(1000),
|
||||
Clock.systemUTC(), this::applyUpdates);
|
||||
metadataChangeListener = new RegistryChangeListener<Metadata>() {
|
||||
@ -131,7 +133,7 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
itemRegistry.getItems().forEach(this::createRootAccessories);
|
||||
initialiseRevision();
|
||||
makeNewConfigurationRevision();
|
||||
logger.info("Created {} HomeKit items.", accessoryRegistry.getAllAccessories().size());
|
||||
logger.info("Created {} HomeKit items in instance {}.", accessoryRegistry.getAllAccessories().size(), instance);
|
||||
}
|
||||
|
||||
private void initialiseRevision() {
|
||||
@ -297,11 +299,9 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
* @return primary accessory type
|
||||
*/
|
||||
private HomekitAccessoryType getPrimaryAccessoryType(Item item,
|
||||
List<Entry<HomekitAccessoryType, HomekitCharacteristicType>> accessoryTypes) {
|
||||
if (accessoryTypes.size() > 1) {
|
||||
final @Nullable Map<String, Object> configuration = HomekitAccessoryFactory.getItemConfiguration(item,
|
||||
metadataRegistry);
|
||||
if (configuration != null) {
|
||||
List<Entry<HomekitAccessoryType, HomekitCharacteristicType>> accessoryTypes,
|
||||
@Nullable Map<String, Object> configuration) {
|
||||
if (accessoryTypes.size() > 1 && configuration != null) {
|
||||
final @Nullable Object value = configuration.get(HomekitTaggedItem.PRIMARY_SERVICE);
|
||||
if (value instanceof String) {
|
||||
return accessoryTypes.stream()
|
||||
@ -309,7 +309,6 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
.orElse(accessoryTypes.get(0)).getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
// no primary accessory found or there is only one type, so return the first type from the list
|
||||
return accessoryTypes.get(0).getKey();
|
||||
}
|
||||
@ -358,14 +357,20 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
final List<Entry<HomekitAccessoryType, HomekitCharacteristicType>> accessoryTypes = HomekitAccessoryFactory
|
||||
.getAccessoryTypes(item, metadataRegistry);
|
||||
final List<GroupItem> groups = HomekitAccessoryFactory.getAccessoryGroups(item, itemRegistry, metadataRegistry);
|
||||
if (!accessoryTypes.isEmpty()
|
||||
&& (groups.isEmpty() || groups.stream().noneMatch(g -> g.getBaseItem() == null))) {
|
||||
final HomekitAccessoryType primaryAccessoryType = getPrimaryAccessoryType(item, accessoryTypes);
|
||||
logger.trace("Item {} is a HomeKit accessory of types {}. Primary type is {}", item.getName(),
|
||||
accessoryTypes, primaryAccessoryType);
|
||||
final @Nullable Map<String, Object> itemConfiguration = HomekitAccessoryFactory.getItemConfiguration(item,
|
||||
metadataRegistry);
|
||||
if (accessoryTypes.isEmpty() || !(groups.isEmpty() || groups.stream().noneMatch(g -> g.getBaseItem() == null))
|
||||
|| !itemIsForThisBridge(item, itemConfiguration)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final HomekitAccessoryType primaryAccessoryType = getPrimaryAccessoryType(item, accessoryTypes,
|
||||
itemConfiguration);
|
||||
logger.trace("Item {} is a HomeKit accessory of types {}. Primary type is {}", item.getName(), accessoryTypes,
|
||||
primaryAccessoryType);
|
||||
final HomekitOHItemProxy itemProxy = new HomekitOHItemProxy(item);
|
||||
final HomekitTaggedItem taggedItem = new HomekitTaggedItem(new HomekitOHItemProxy(item),
|
||||
primaryAccessoryType, HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry));
|
||||
final HomekitTaggedItem taggedItem = new HomekitTaggedItem(new HomekitOHItemProxy(item), primaryAccessoryType,
|
||||
itemConfiguration);
|
||||
try {
|
||||
final HomekitAccessory accessory = HomekitAccessoryFactory.create(taggedItem, metadataRegistry, updater,
|
||||
settings);
|
||||
@ -373,8 +378,7 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
accessoryTypes.stream().filter(aType -> !primaryAccessoryType.equals(aType.getKey()))
|
||||
.forEach(additionalAccessoryType -> {
|
||||
final HomekitTaggedItem additionalTaggedItem = new HomekitTaggedItem(itemProxy,
|
||||
additionalAccessoryType.getKey(),
|
||||
HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry));
|
||||
additionalAccessoryType.getKey(), itemConfiguration);
|
||||
try {
|
||||
final HomekitAccessory additionalAccessory = HomekitAccessoryFactory
|
||||
.create(additionalTaggedItem, metadataRegistry, updater, settings);
|
||||
@ -388,5 +392,22 @@ public class HomekitChangeListener implements ItemRegistryChangeListener {
|
||||
logger.warn("Cannot create accessory {}", taggedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean itemIsForThisBridge(Item item, @Nullable Map<String, Object> configuration) {
|
||||
// non-tagged accessories belong to the first instance
|
||||
if (configuration == null) {
|
||||
return (instance == 1);
|
||||
}
|
||||
|
||||
final @Nullable Object value = configuration.get(HomekitTaggedItem.INSTANCE);
|
||||
if (value == null) {
|
||||
return (instance == 1);
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
return (instance == ((Number) value).intValue());
|
||||
}
|
||||
logger.warn("Unrecognized instance tag {} ({}) for item {}; assigning to default instance.", value,
|
||||
value.getClass(), item.getName());
|
||||
return (instance == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,18 +69,20 @@ import io.github.hapjava.server.impl.crypto.HAPSetupCodeUtils;
|
||||
public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(HomekitImpl.class);
|
||||
|
||||
private final StorageService storageService;
|
||||
private final NetworkAddressService networkAddressService;
|
||||
private final ConfigurationAdmin configAdmin;
|
||||
private final Storage<String> storage;
|
||||
private final ItemRegistry itemRegistry;
|
||||
private final MetadataRegistry metadataRegistry;
|
||||
|
||||
private HomekitAuthInfoImpl authInfo;
|
||||
private final List<HomekitAuthInfoImpl> authInfos = new ArrayList<>();
|
||||
private HomekitSettings settings;
|
||||
private @Nullable InetAddress networkInterface;
|
||||
private @Nullable HomekitServer homekitServer;
|
||||
private @Nullable HomekitRoot bridge;
|
||||
private final List<HomekitServer> homekitServers = new ArrayList<>();
|
||||
private final List<HomekitRoot> bridges = new ArrayList<>();
|
||||
private MDNSClient mdnsClient;
|
||||
|
||||
private final HomekitChangeListener changeListener;
|
||||
private final List<HomekitChangeListener> changeListeners = new ArrayList<>();
|
||||
|
||||
private final ScheduledExecutorService scheduler = ThreadPoolManager
|
||||
.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON);
|
||||
@ -90,15 +92,15 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
@Reference NetworkAddressService networkAddressService, @Reference MetadataRegistry metadataRegistry,
|
||||
@Reference ConfigurationAdmin configAdmin, @Reference MDNSClient mdnsClient, Map<String, Object> properties)
|
||||
throws IOException, InvalidAlgorithmParameterException {
|
||||
this.storageService = storageService;
|
||||
this.networkAddressService = networkAddressService;
|
||||
this.configAdmin = configAdmin;
|
||||
this.settings = processConfig(properties);
|
||||
this.mdnsClient = mdnsClient;
|
||||
this.storage = storageService.getStorage(HomekitAuthInfoImpl.STORAGE_KEY);
|
||||
this.itemRegistry = itemRegistry;
|
||||
this.metadataRegistry = metadataRegistry;
|
||||
networkAddressService.addNetworkAddressChangeListener(this);
|
||||
this.changeListener = new HomekitChangeListener(itemRegistry, settings, metadataRegistry, storage);
|
||||
try {
|
||||
authInfo = new HomekitAuthInfoImpl(storage, settings.pin, settings.setupId, settings.blockUserDeletion);
|
||||
startHomekitServer();
|
||||
} catch (IOException | InvalidAlgorithmParameterException e) {
|
||||
logger.warn("cannot activate HomeKit binding. {}", e.getMessage());
|
||||
@ -150,42 +152,35 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
settings = processConfig(config);
|
||||
if ((oldSettings == null) || (settings == null))
|
||||
return;
|
||||
changeListener.updateSettings(settings);
|
||||
if (!oldSettings.networkInterface.equals(settings.networkInterface) || oldSettings.port != settings.port
|
||||
|| oldSettings.useOHmDNS != settings.useOHmDNS) {
|
||||
if (!oldSettings.name.equals(settings.name) || !oldSettings.pin.equals(settings.pin)
|
||||
|| !oldSettings.setupId.equals(settings.setupId)
|
||||
|| !oldSettings.networkInterface.equals(settings.networkInterface)
|
||||
|| oldSettings.port != settings.port || oldSettings.useOHmDNS != settings.useOHmDNS
|
||||
|| oldSettings.instances != settings.instances) {
|
||||
// the HomeKit server settings changed. we do a complete re-init
|
||||
stopHomekitServer();
|
||||
startHomekitServer();
|
||||
} else if (!oldSettings.name.equals(settings.name) || !oldSettings.pin.equals(settings.pin)
|
||||
|| !oldSettings.setupId.equals(settings.setupId)) {
|
||||
stopHomekitServer();
|
||||
authInfo.setPin(settings.pin);
|
||||
authInfo.setSetupId(settings.setupId);
|
||||
startHomekitServer();
|
||||
} else {
|
||||
for (HomekitChangeListener changeListener : changeListeners) {
|
||||
changeListener.updateSettings(settings);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} catch (IOException | InvalidAlgorithmParameterException e) {
|
||||
logger.warn("could not initialize HomeKit bridge: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void stopBridge() {
|
||||
final @Nullable HomekitRoot bridge = this.bridge;
|
||||
if (bridge != null) {
|
||||
changeListener.unsetBridge();
|
||||
bridge.stop();
|
||||
this.bridge = null;
|
||||
private HomekitRoot startBridge(HomekitServer homekitServer, HomekitAuthInfoImpl authInfo,
|
||||
HomekitChangeListener changeListener, int instance) throws IOException {
|
||||
String name = settings.name;
|
||||
if (instance != 1) {
|
||||
name += " (" + instance + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private void startBridge() throws IOException {
|
||||
final @Nullable HomekitServer homekitServer = this.homekitServer;
|
||||
if (homekitServer != null && bridge == null) {
|
||||
final HomekitRoot bridge = homekitServer.createBridge(authInfo, settings.name,
|
||||
HomekitAccessoryCategories.BRIDGES, HomekitSettings.MANUFACTURER, HomekitSettings.MODEL,
|
||||
HomekitSettings.SERIAL_NUMBER, FrameworkUtil.getBundle(getClass()).getVersion().toString(),
|
||||
HomekitSettings.HARDWARE_REVISION);
|
||||
final HomekitRoot bridge = homekitServer.createBridge(authInfo, name, HomekitAccessoryCategories.BRIDGES,
|
||||
HomekitSettings.MANUFACTURER, HomekitSettings.MODEL, HomekitSettings.SERIAL_NUMBER,
|
||||
FrameworkUtil.getBundle(getClass()).getVersion().toString(), HomekitSettings.HARDWARE_REVISION);
|
||||
changeListener.setBridge(bridge);
|
||||
this.bridge = bridge;
|
||||
bridges.add(bridge);
|
||||
bridge.setConfigurationIndex(changeListener.getConfigurationRevision());
|
||||
bridge.refreshAuthInfo();
|
||||
final int lastAccessoryCount = changeListener.getLastAccessoryCount();
|
||||
@ -205,26 +200,39 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
} else { // start bridge immediately.
|
||||
bridge.start();
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"trying to start bridge but HomeKit server is not initialized or bridge is already initialized");
|
||||
}
|
||||
return bridge;
|
||||
}
|
||||
|
||||
private void startHomekitServer() throws IOException {
|
||||
private void startHomekitServer() throws IOException, InvalidAlgorithmParameterException {
|
||||
logger.trace("start HomeKit bridge");
|
||||
if (homekitServer == null) {
|
||||
if (homekitServers.isEmpty()) {
|
||||
try {
|
||||
networkInterface = InetAddress
|
||||
.getByName(((settings.networkInterface != null) && (!settings.networkInterface.isEmpty()))
|
||||
? settings.networkInterface
|
||||
: networkAddressService.getPrimaryIpv4HostAddress());
|
||||
} catch (UnknownHostException e) {
|
||||
logger.warn("cannot resolve the Pv4 address / hostname {}.",
|
||||
networkAddressService.getPrimaryIpv4HostAddress());
|
||||
}
|
||||
|
||||
for (int i = 0; i < settings.instances; ++i) {
|
||||
String storage_key = HomekitAuthInfoImpl.STORAGE_KEY;
|
||||
if (i != 0) {
|
||||
storage_key += i;
|
||||
}
|
||||
Storage<String> storage = storageService.getStorage(storage_key);
|
||||
HomekitAuthInfoImpl authInfo = new HomekitAuthInfoImpl(storage, settings.pin, settings.setupId,
|
||||
settings.blockUserDeletion);
|
||||
|
||||
@Nullable
|
||||
HomekitServer homekitServer = null;
|
||||
if (settings.useOHmDNS) {
|
||||
for (JmDNS mdns : mdnsClient.getClientInstances()) {
|
||||
if (mdns.getInetAddress().equals(networkInterface)) {
|
||||
logger.trace("suitable mDNS client for IP {} found and will be used for HomeKit",
|
||||
networkInterface);
|
||||
homekitServer = new HomekitServer(mdns, settings.port);
|
||||
homekitServer = new HomekitServer(mdns, settings.port + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,12 +241,14 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
logger.trace("no suitable mDNS server for IP {} found", networkInterface);
|
||||
}
|
||||
logger.trace("create HomeKit server with dedicated mDNS server");
|
||||
homekitServer = new HomekitServer(networkInterface, settings.port);
|
||||
homekitServer = new HomekitServer(networkInterface, settings.port + i);
|
||||
}
|
||||
startBridge();
|
||||
} catch (UnknownHostException e) {
|
||||
logger.warn("cannot resolve the Pv4 address / hostname {}.",
|
||||
networkAddressService.getPrimaryIpv4HostAddress());
|
||||
homekitServers.add(homekitServer);
|
||||
HomekitChangeListener changeListener = new HomekitChangeListener(itemRegistry, settings,
|
||||
metadataRegistry, storage, i + 1);
|
||||
changeListeners.add(changeListener);
|
||||
bridges.add(startBridge(homekitServer, authInfo, changeListener, i + 1));
|
||||
authInfos.add(authInfo);
|
||||
}
|
||||
} else {
|
||||
logger.warn("trying to start HomeKit server but it is already initialized");
|
||||
@ -247,49 +257,56 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
|
||||
private void stopHomekitServer() {
|
||||
logger.trace("stop HomeKit bridge");
|
||||
final @Nullable HomekitServer homekit = this.homekitServer;
|
||||
if (homekit != null) {
|
||||
if (bridge != null) {
|
||||
stopBridge();
|
||||
}
|
||||
homekit.stop();
|
||||
this.homekitServer = null;
|
||||
for (int i = 0; i < homekitServers.size(); ++i) {
|
||||
changeListeners.get(i).unsetBridge();
|
||||
bridges.get(i).stop();
|
||||
homekitServers.get(i).stop();
|
||||
changeListeners.get(i).stop();
|
||||
}
|
||||
homekitServers.clear();
|
||||
bridges.clear();
|
||||
changeListeners.clear();
|
||||
authInfos.clear();
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate() {
|
||||
networkAddressService.removeNetworkAddressChangeListener(this);
|
||||
for (HomekitChangeListener changeListener : changeListeners) {
|
||||
changeListener.clearAccessories();
|
||||
}
|
||||
stopHomekitServer();
|
||||
changeListener.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshAuthInfo() throws IOException {
|
||||
final @Nullable HomekitRoot bridge = this.bridge;
|
||||
if (bridge != null) {
|
||||
for (HomekitRoot bridge : bridges) {
|
||||
bridge.refreshAuthInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void allowUnauthenticatedRequests(boolean allow) {
|
||||
final @Nullable HomekitRoot bridge = this.bridge;
|
||||
if (bridge != null) {
|
||||
for (HomekitRoot bridge : bridges) {
|
||||
bridge.allowUnauthenticatedRequests(allow);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HomekitAccessory> getAccessories() {
|
||||
return new ArrayList<>(this.changeListener.getAccessories().values());
|
||||
List<HomekitAccessory> accessories = new ArrayList<>();
|
||||
for (HomekitChangeListener changeListener : changeListeners) {
|
||||
accessories.addAll(changeListener.getAccessories().values());
|
||||
}
|
||||
return accessories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearHomekitPairings() {
|
||||
try {
|
||||
for (HomekitAuthInfoImpl authInfo : authInfos) {
|
||||
authInfo.clear();
|
||||
}
|
||||
refreshAuthInfo();
|
||||
} catch (Exception e) {
|
||||
logger.warn("could not clear HomeKit pairings", e);
|
||||
@ -302,23 +319,13 @@ public class HomekitImpl implements Homekit, NetworkAddressChangeListener {
|
||||
removed.forEach(i -> {
|
||||
logger.trace("removed interface {}", i.getAddress().toString());
|
||||
if (i.getAddress().equals(networkInterface)) {
|
||||
final @Nullable HomekitRoot bridge = this.bridge;
|
||||
if (bridge != null) {
|
||||
bridge.stop();
|
||||
this.bridge = null;
|
||||
}
|
||||
final @Nullable HomekitServer homekitServer = this.homekitServer;
|
||||
if (homekitServer != null) {
|
||||
homekitServer.stop();
|
||||
this.homekitServer = null;
|
||||
}
|
||||
logger.trace("bridge stopped");
|
||||
stopHomekitServer();
|
||||
}
|
||||
});
|
||||
if ((this.bridge == null) && (!added.isEmpty())) {
|
||||
if (bridges.isEmpty() && !added.isEmpty()) {
|
||||
try {
|
||||
startHomekitServer();
|
||||
} catch (IOException e) {
|
||||
} catch (IOException | InvalidAlgorithmParameterException e) {
|
||||
logger.warn("could not initialize HomeKit bridge: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ public class HomekitSettings {
|
||||
|
||||
public String name = "openHAB";
|
||||
public int port = 9123;
|
||||
public int instances = 1;
|
||||
public String pin = "031-45-154";
|
||||
public String setupId;
|
||||
public String qrCode;
|
||||
@ -92,6 +93,9 @@ public class HomekitSettings {
|
||||
if (port != other.port) {
|
||||
return false;
|
||||
}
|
||||
if (instances != other.instances) {
|
||||
return false;
|
||||
}
|
||||
if (thermostatTargetModeAuto == null) {
|
||||
if (other.thermostatTargetModeAuto != null) {
|
||||
return false;
|
||||
|
||||
@ -43,6 +43,7 @@ public class HomekitTaggedItem {
|
||||
public final static String DELAY = "commandDelay";
|
||||
public final static String INVERTED = "inverted";
|
||||
public final static String PRIMARY_SERVICE = "primary";
|
||||
public final static String INSTANCE = "instance";
|
||||
|
||||
private static final Map<Integer, String> CREATED_ACCESSORY_IDS = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
@ -41,6 +41,12 @@
|
||||
<description>Defines the port the HomeKit integration listens on.</description>
|
||||
<default>9123</default>
|
||||
</parameter>
|
||||
<parameter name="instances" type="integer" required="true" groupName="core">
|
||||
<label>Instances</label>
|
||||
<description>Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be
|
||||
assigned to additional instances via metadata. Additional bridges will use incrementing port numbers.</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
<parameter name="pin" type="text" pattern="\d{3}-\d{2}-\d{3}" required="true" groupName="core">
|
||||
<label>Pin</label>
|
||||
<description>Defines the pin, used for pairing, in the form ###-##-###.</description>
|
||||
|
||||
@ -9,6 +9,8 @@ io.config.homekit.group.thermostatCurrentHeatingCooling.label = Thermostat Curre
|
||||
io.config.homekit.group.thermostatCurrentHeatingCooling.description = String values used by your thermostat to set different targetHeatingCooling modes
|
||||
io.config.homekit.group.thermostatTargetHeatingCooling.label = Thermostat Target Heating/Cooling Mapping
|
||||
io.config.homekit.group.thermostatTargetHeatingCooling.description = String values used by your thermostat to set different targetHeatingCooling modes
|
||||
io.config.homekit.instances.label = Instances
|
||||
io.config.homekit.instances.description = Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be assigned to additional instances via metadata. Additional bridges will use incrementing port numbers.
|
||||
io.config.homekit.name.label = Bridge name
|
||||
io.config.homekit.name.description = Name of the HomeKit bridge
|
||||
io.config.homekit.networkInterface.label = Network Interface
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user