Skip to content

Commit 819a5c2

Browse files
committed
Add and direct implementors to use LowBatteryStatusAccessory
BatteryAccessory is used only by BatteryService and does not apply to MotionSensor, SmokeSensor, etc. Deprecate BatteryAccessory and leave the implementation for BatteryService / Battery for a future date. Log a warning for accessories that are still trying to use it.
1 parent e64bf79 commit 819a5c2

File tree

10 files changed

+174
-75
lines changed

10 files changed

+174
-75
lines changed

src/main/java/com/beowulfe/hap/accessories/BatteryAccessory.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.beowulfe.hap.accessories;
22

3-
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
4-
53
import java.util.concurrent.CompletableFuture;
64

5+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
6+
77
/**
8-
* An accessory that runs on batteries. Accessories that run on batteries are able to report
9-
* battery level.
8+
* Do not use. Devices that have battery levels should implement LowBatteryStatusAccessory.
109
*
1110
* @author Gaston Dombiak
1211
*/
12+
@Deprecated
1313
public interface BatteryAccessory {
1414

1515
/**
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.beowulfe.hap.accessories;
2+
3+
import java.util.concurrent.CompletableFuture;
4+
5+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
6+
7+
/**
8+
* An accessory that runs on batteries. Accessories that run on batteries are able to report
9+
* battery level.
10+
*
11+
* @author Tim Harper
12+
*/
13+
public interface BatteryStatusAccessory {
14+
15+
/**
16+
* Queries if the device battery level is low; returning a value of true
17+
* will cause a low-battery status to appear in Home for the device.
18+
*
19+
* @return a future that will contain the accessory's low battery state
20+
*/
21+
CompletableFuture<Boolean> getLowBatteryState();
22+
23+
/**
24+
* Subscribes to changes in the battery level.
25+
*
26+
* @param callback the function to call when low battery state changes.
27+
*/
28+
void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback);
29+
30+
/**
31+
* Unsubscribes from changes in the low battery state.
32+
*/
33+
void unsubscribeLowBatteryState();
34+
}

src/main/java/com/beowulfe/hap/accessories/CarbonMonoxideSensor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* <p>A carbon monoxide sensor reports whether carbon monoxide has been detected or not.</p>
1515
*
1616
* <p>Carbon monoxide sensors that run on batteries will need to implement this interface
17-
* and also implement {@link BatteryAccessory}.</p>
17+
* and also implement {@link BatteryStatusAccessory}.</p>
1818
*
1919
* @author Gaston Dombiak
2020
*/

src/main/java/com/beowulfe/hap/accessories/ContactSensor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* that the door/window is closed.</p>
1717
*
1818
* <p>Contact sensors that run on batteries will need to implement this interface
19-
* and also implement {@link BatteryAccessory}.</p>
19+
* and also implement {@link BatteryStatusAccessory}.</p>
2020
*
2121
* @author Gaston Dombiak
2222
*/

src/main/java/com/beowulfe/hap/accessories/LockMechanism.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* {@link LockableLockMechanism}.</p>
1616
*
1717
* <p>Locks that run on batteries will need to implement this interface and also
18-
* implement {@link BatteryAccessory}.</p>
18+
* implement {@link BatteryStatusAccessory}.</p>
1919
*
2020
* @author Andy Lintner
2121
*/

src/main/java/com/beowulfe/hap/accessories/MotionSensor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* <p>A motion sensor that reports whether motion has been detected.</p>
1414
*
1515
* <p>Motion sensors that run on batteries will need to implement this interface
16-
* and also implement {@link BatteryAccessory}.</p>
16+
* and also implement {@link BatteryStatusAccessory}.</p>
1717
*
1818
* @author Gaston Dombiak
1919
*/

src/main/java/com/beowulfe/hap/accessories/SmokeSensor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* <p>A smoke sensor reports whether smoke has been detected or not.</p>
1515
*
1616
* <p>Smoke sensors that run on batteries will need to implement this interface
17-
* and also implement {@link BatteryAccessory}.</p>
17+
* and also implement {@link BatteryStatusAccessory}.</p>
1818
*
1919
* @author Gaston Dombiak
2020
*/

src/main/java/com/beowulfe/hap/impl/characteristics/common/BatteryLevelCharacteristic.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
package com.beowulfe.hap.impl.characteristics.common;
22

3-
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
4-
import com.beowulfe.hap.characteristics.EventableCharacteristic;
5-
import com.beowulfe.hap.characteristics.IntegerCharacteristic;
6-
73
import java.util.concurrent.CompletableFuture;
84
import java.util.function.Consumer;
95
import java.util.function.Supplier;
106

7+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
8+
import com.beowulfe.hap.characteristics.EventableCharacteristic;
9+
import com.beowulfe.hap.characteristics.IntegerCharacteristic;
10+
11+
/**
12+
* This characteristic is used by a stand-alone BatteryService, which describes
13+
* a stand-alone battery device, not the battery status of a battery operated
14+
* device such as a motion sensor.
15+
*/
1116
public class BatteryLevelCharacteristic extends IntegerCharacteristic implements EventableCharacteristic {
1217

1318
private final Supplier<CompletableFuture<Integer>> getter;
1419
private final Consumer<HomekitCharacteristicChangeCallback> subscriber;
1520
private final Runnable unsubscriber;
1621

1722
public BatteryLevelCharacteristic(Supplier<CompletableFuture<Integer>> getter,
18-
Consumer<HomekitCharacteristicChangeCallback> subscriber, Runnable unsubscriber) {
23+
Consumer<HomekitCharacteristicChangeCallback> subscriber, Runnable unsubscriber) {
1924
super("00000068-0000-1000-8000-0026BB765291", false, true, "Battery Level", 0, 100, "%");
2025
this.getter = getter;
2126
this.subscriber = subscriber;
@@ -29,7 +34,7 @@ protected CompletableFuture<Integer> getValue() {
2934

3035
@Override
3136
protected void setValue(Integer value) throws Exception {
32-
//Read Only
37+
// Read Only
3338
}
3439

3540
@Override
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.beowulfe.hap.impl.characteristics.common;
2+
3+
import java.util.concurrent.CompletableFuture;
4+
import java.util.function.Consumer;
5+
import java.util.function.Supplier;
6+
7+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
8+
import com.beowulfe.hap.characteristics.BooleanCharacteristic;
9+
import com.beowulfe.hap.characteristics.EventableCharacteristic;
10+
11+
public class LowBatteryStatusCharacteristic extends BooleanCharacteristic implements EventableCharacteristic {
12+
13+
private final Supplier<CompletableFuture<Boolean>> getter;
14+
private final Consumer<HomekitCharacteristicChangeCallback> subscriber;
15+
private final Runnable unsubscriber;
16+
17+
public LowBatteryStatusCharacteristic(Supplier<CompletableFuture<Boolean>> getter,
18+
Consumer<HomekitCharacteristicChangeCallback> subscriber, Runnable unsubscriber) {
19+
super("00000079-0000-1000-8000-0026BB765291", false, true, "Status Low Battery");
20+
this.getter = getter;
21+
this.subscriber = subscriber;
22+
this.unsubscriber = unsubscriber;
23+
}
24+
25+
@Override
26+
protected CompletableFuture<Boolean> getValue() {
27+
return getter.get();
28+
}
29+
30+
@Override
31+
protected void setValue(Boolean value) throws Exception {
32+
// Read Only
33+
}
34+
35+
@Override
36+
public void subscribe(HomekitCharacteristicChangeCallback callback) {
37+
subscriber.accept(callback);
38+
}
39+
40+
@Override
41+
public void unsubscribe() {
42+
unsubscriber.run();
43+
}
44+
}
Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,93 @@
11
package com.beowulfe.hap.impl.services;
22

3+
import java.util.Collections;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
310
import com.beowulfe.hap.HomekitAccessory;
411
import com.beowulfe.hap.Service;
512
import com.beowulfe.hap.accessories.BatteryAccessory;
13+
import com.beowulfe.hap.accessories.BatteryStatusAccessory;
614
import com.beowulfe.hap.characteristics.Characteristic;
715
import com.beowulfe.hap.impl.characteristics.common.BatteryLevelCharacteristic;
16+
import com.beowulfe.hap.impl.characteristics.common.LowBatteryStatusCharacteristic;
817
import com.beowulfe.hap.impl.characteristics.common.Name;
918

10-
import java.util.Collections;
11-
import java.util.LinkedList;
12-
import java.util.List;
13-
1419
abstract class AbstractServiceImpl implements Service {
15-
16-
private final String type;
17-
private final List<Characteristic> characteristics = new LinkedList<>();
20+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
21+
private final String type;
22+
private final List<Characteristic> characteristics = new LinkedList<>();
1823

19-
/**
20-
* This constructor has been deprecated and replaced with
21-
* {@link #AbstractServiceImpl(String, HomekitAccessory, String)}. Usages of
22-
* this constructor will need to manually configure {@link Name} characteristic
23-
* and {@link BatteryLevelCharacteristic} if needed.
24-
*
25-
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
26-
*/
27-
@Deprecated
28-
public AbstractServiceImpl(String type) {
29-
this(type, null, null);
30-
}
24+
/**
25+
* This constructor has been deprecated and replaced with
26+
* {@link #AbstractServiceImpl(String, HomekitAccessory, String)}. Usages of
27+
* this constructor will need to manually configure {@link Name} characteristic
28+
* and {@link BatteryLevelCharacteristic} if needed.
29+
*
30+
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
31+
*/
32+
@Deprecated
33+
public AbstractServiceImpl(String type) {
34+
this(type, null, null);
35+
}
3136

32-
/**
33-
* <p>Creates a new instance of this class with the specified UUID and {@link HomekitAccessory}.
34-
* Download and install <i>HomeKit Accessory Simulator</i> to discover the corresponding UUID for
35-
* the specific service.</p>
36-
*
37-
* <p>The new service will automatically add {@link Name} characteristic. If the accessory
38-
* is battery operated then it must implement {@link BatteryAccessory} and {@link BatteryLevelCharacteristic}
39-
* will be added too.</p>
40-
*
41-
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
42-
* @param accessory HomeKit accessory exposed as a service.
43-
* @param serviceName name of the service. This information is usually the name of the accessory.
37+
/**
38+
* <p>
39+
* Creates a new instance of this class with the specified UUID and {@link HomekitAccessory}.
40+
* Download and install <i>HomeKit Accessory Simulator</i> to discover the corresponding UUID for
41+
* the specific service.
42+
* </p>
43+
*
44+
* <p>
45+
* The new service will automatically add {@link Name} characteristic. If the accessory
46+
* is battery operated then it must implement {@link BatteryAccessory} and {@link BatteryLevelCharacteristic}
47+
* will be added too.
48+
* </p>
49+
*
50+
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
51+
* @param accessory HomeKit accessory exposed as a service.
52+
* @param serviceName name of the service. This information is usually the name of the accessory.
4453
*/
45-
public AbstractServiceImpl(String type, HomekitAccessory accessory, String serviceName) {
46-
this.type = type;
54+
public AbstractServiceImpl(String type, HomekitAccessory accessory, String serviceName) {
55+
this.type = type;
56+
57+
if (accessory != null) {
58+
// Add name characteristic
59+
addCharacteristic(new Name(serviceName));
60+
61+
// If battery operated accessory then add BatteryLevelCharacteristic
62+
if (accessory instanceof BatteryAccessory) {
63+
logger.warn(
64+
"Accessory {} implements BatteryAccessory, which was incorrectly used to advertise battery state and is not recognized by HomeKit. "
65+
+ "Battery-powered devices should report their battery status using LowBatteryStatusAccessory",
66+
accessory.getClass());
67+
}
68+
69+
// If battery operated accessory then add LowBatteryStatusAccessory
70+
if (accessory instanceof BatteryStatusAccessory) {
71+
BatteryStatusAccessory batteryStatusAccessory = (BatteryStatusAccessory) accessory;
72+
addCharacteristic(new LowBatteryStatusCharacteristic(batteryStatusAccessory::getLowBatteryState,
73+
batteryStatusAccessory::subscribeLowBatteryState,
74+
batteryStatusAccessory::unsubscribeLowBatteryState));
75+
76+
}
77+
}
78+
}
4779

48-
if (accessory != null) {
49-
// Add name characteristic
50-
addCharacteristic(new Name(serviceName));
80+
@Override
81+
public List<Characteristic> getCharacteristics() {
82+
return Collections.unmodifiableList(characteristics);
83+
}
5184

52-
// If battery operated accessory then add BatteryLevelCharacteristic
53-
if (accessory instanceof BatteryAccessory) {
54-
BatteryAccessory batteryAccessory = (BatteryAccessory) accessory;
55-
addCharacteristic(new BatteryLevelCharacteristic(
56-
batteryAccessory::getBatteryLevelState,
57-
batteryAccessory::subscribeBatteryLevelState,
58-
batteryAccessory::unsubscribeBatteryLevelState
59-
));
60-
}
61-
}
62-
}
85+
@Override
86+
public String getType() {
87+
return type;
88+
}
6389

64-
@Override
65-
public List<Characteristic> getCharacteristics() {
66-
return Collections.unmodifiableList(characteristics);
67-
}
68-
69-
@Override
70-
public String getType() {
71-
return type;
72-
}
73-
74-
protected void addCharacteristic(Characteristic characteristic) {
75-
this.characteristics.add(characteristic);
76-
}
90+
protected void addCharacteristic(Characteristic characteristic) {
91+
this.characteristics.add(characteristic);
92+
}
7793
}

0 commit comments

Comments
 (0)