Skip to content

Commit de167b0

Browse files
committed
Added support for battery levels. Contact sensors, motion sensors and locks can now report battery levels.
1 parent ca24bb1 commit de167b0

File tree

8 files changed

+134
-11
lines changed

8 files changed

+134
-11
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.beowulfe.hap.accessories;
2+
3+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
4+
5+
import java.util.concurrent.CompletableFuture;
6+
7+
/**
8+
* An accessory that runs on batteries. Accessories that run on batteries are able to report
9+
* battery level.
10+
*
11+
* @author Gaston Dombiak
12+
*/
13+
public interface BatteryAccessory {
14+
15+
/**
16+
* Retrieves the battery level of the accessory.
17+
*
18+
* @return a future that will contain the accessory's battery state
19+
*/
20+
CompletableFuture<Integer> getBatteryLevelState();
21+
22+
/**
23+
* Subscribes to changes in the battery level.
24+
*
25+
* @param callback the function to call when battery level changes.
26+
*/
27+
void subscribeBatteryLevelState(HomekitCharacteristicChangeCallback callback);
28+
29+
/**
30+
* Unsubscribes from changes in the battery level.
31+
*/
32+
void unsubscribeBatteryLevelState();
33+
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@
1111
import java.util.concurrent.CompletableFuture;
1212

1313
/**
14-
* A contact sensor that reports whether contact is detected or not. Typical
14+
* <p>A contact sensor that reports whether contact is detected or not. Typical
1515
* contact sensors are window/door sensors. When contact is detected it means
16-
* that the door/window is closed.
16+
* that the door/window is closed.</p>
17+
*
18+
* <p>Contact sensors that run on batteries will need to implement this interface
19+
* and also implement {@link BatteryAccessory}.</p>
20+
*
21+
* @author Gaston Dombiak
1722
*/
1823
public interface ContactSensor extends HomekitAccessory {
1924

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

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

3+
import com.beowulfe.hap.HomekitAccessory;
4+
import com.beowulfe.hap.HomekitCharacteristicChangeCallback;
5+
import com.beowulfe.hap.Service;
6+
import com.beowulfe.hap.accessories.properties.LockMechanismState;
7+
import com.beowulfe.hap.impl.services.LockMechanismService;
8+
39
import java.util.Collection;
410
import java.util.Collections;
511
import java.util.concurrent.CompletableFuture;
612

7-
import com.beowulfe.hap.*;
8-
import com.beowulfe.hap.accessories.properties.LockMechanismState;
9-
import com.beowulfe.hap.impl.services.LockMechanismService;
10-
1113
/**
12-
* A lock capable of exposing its binary locked state. For a lock that can be locked/unlocked, use
13-
* {@link LockableLockMechanism}
14+
* <p>A lock capable of exposing its binary locked state. For a lock that can be locked/unlocked, use
15+
* {@link LockableLockMechanism}.</p>
16+
*
17+
* <p>Locks that run on batteries will need to implement this interface and also
18+
* implement {@link BatteryAccessory}.</p>
1419
*
1520
* @author Andy Lintner
1621
*/

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
import java.util.concurrent.CompletableFuture;
1111

1212
/**
13-
* A motion sensor that reports whether motion has been detected.
13+
* <p>A motion sensor that reports whether motion has been detected.</p>
14+
*
15+
* <p>Motion sensors that run on batteries will need to implement this interface
16+
* and also implement {@link BatteryAccessory}.</p>
17+
*
18+
* @author Gaston Dombiak
1419
*/
1520
public interface MotionSensor extends HomekitAccessory {
1621

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 com.beowulfe.hap.HomekitCharacteristicChangeCallback;
4+
import com.beowulfe.hap.characteristics.EventableCharacteristic;
5+
import com.beowulfe.hap.characteristics.IntegerCharacteristic;
6+
7+
import java.util.concurrent.CompletableFuture;
8+
import java.util.function.Consumer;
9+
import java.util.function.Supplier;
10+
11+
public class BatteryLevelCharacteristic extends IntegerCharacteristic implements EventableCharacteristic {
12+
13+
private final Supplier<CompletableFuture<Integer>> getter;
14+
private final Consumer<HomekitCharacteristicChangeCallback> subscriber;
15+
private final Runnable unsubscriber;
16+
17+
public BatteryLevelCharacteristic(Supplier<CompletableFuture<Integer>> getter,
18+
Consumer<HomekitCharacteristicChangeCallback> subscriber, Runnable unsubscriber) {
19+
super("00000068-0000-1000-8000-0026BB765291", false, true, "Battery Level", 0, 100, "%");
20+
this.getter = getter;
21+
this.subscriber = subscriber;
22+
this.unsubscriber = unsubscriber;
23+
}
24+
25+
@Override
26+
protected CompletableFuture<Integer> getValue() {
27+
return getter.get();
28+
}
29+
30+
@Override
31+
protected void setValue(Integer 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+
}

src/main/java/com/beowulfe/hap/impl/services/ContactSensorService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.beowulfe.hap.impl.services;
22

3+
import com.beowulfe.hap.accessories.BatteryAccessory;
34
import com.beowulfe.hap.accessories.ContactSensor;
5+
import com.beowulfe.hap.impl.characteristics.common.BatteryLevelCharacteristic;
46
import com.beowulfe.hap.impl.characteristics.common.Name;
57
import com.beowulfe.hap.impl.characteristics.contactsensor.ContactSensorStateCharacteristic;
68

@@ -10,5 +12,14 @@ public ContactSensorService(ContactSensor contactSensor) {
1012
super("00000080-0000-1000-8000-0026BB765291");
1113
addCharacteristic(new Name(contactSensor));
1214
addCharacteristic(new ContactSensorStateCharacteristic(contactSensor));
15+
16+
if (contactSensor instanceof BatteryAccessory) {
17+
BatteryAccessory batteryAccessory = (BatteryAccessory) contactSensor;
18+
addCharacteristic(new BatteryLevelCharacteristic(
19+
batteryAccessory::getBatteryLevelState,
20+
batteryAccessory::subscribeBatteryLevelState,
21+
batteryAccessory::unsubscribeBatteryLevelState
22+
));
23+
}
1324
}
1425
}

src/main/java/com/beowulfe/hap/impl/services/LockMechanismService.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.beowulfe.hap.impl.services;
22

3+
import com.beowulfe.hap.accessories.BatteryAccessory;
34
import com.beowulfe.hap.accessories.LockMechanism;
45
import com.beowulfe.hap.accessories.LockableLockMechanism;
6+
import com.beowulfe.hap.impl.characteristics.common.BatteryLevelCharacteristic;
57
import com.beowulfe.hap.impl.characteristics.common.Name;
68
import com.beowulfe.hap.impl.characteristics.lock.mechanism.CurrentLockMechanismStateCharacteristic;
79
import com.beowulfe.hap.impl.characteristics.lock.mechanism.TargetLockMechanismStateCharacteristic;
@@ -16,7 +18,14 @@ public LockMechanismService(LockMechanism lock) {
1618
if (lock instanceof LockableLockMechanism) {
1719
addCharacteristic(new TargetLockMechanismStateCharacteristic((LockableLockMechanism) lock));
1820
}
19-
20-
}
2121

22+
if (lock instanceof BatteryAccessory) {
23+
BatteryAccessory batteryAccessory = (BatteryAccessory) lock;
24+
addCharacteristic(new BatteryLevelCharacteristic(
25+
batteryAccessory::getBatteryLevelState,
26+
batteryAccessory::subscribeBatteryLevelState,
27+
batteryAccessory::unsubscribeBatteryLevelState
28+
));
29+
}
30+
}
2231
}

src/main/java/com/beowulfe/hap/impl/services/MotionSensorService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.beowulfe.hap.impl.services;
22

3+
import com.beowulfe.hap.accessories.BatteryAccessory;
34
import com.beowulfe.hap.accessories.MotionSensor;
5+
import com.beowulfe.hap.impl.characteristics.common.BatteryLevelCharacteristic;
46
import com.beowulfe.hap.impl.characteristics.common.Name;
57
import com.beowulfe.hap.impl.characteristics.motionsensor.MotionDetectedStateCharacteristic;
68

@@ -10,5 +12,14 @@ public MotionSensorService(MotionSensor motionSensor) {
1012
super("00000085-0000-1000-8000-0026BB765291");
1113
addCharacteristic(new Name(motionSensor));
1214
addCharacteristic(new MotionDetectedStateCharacteristic(motionSensor));
15+
16+
if (motionSensor instanceof BatteryAccessory) {
17+
BatteryAccessory batteryAccessory = (BatteryAccessory) motionSensor;
18+
addCharacteristic(new BatteryLevelCharacteristic(
19+
batteryAccessory::getBatteryLevelState,
20+
batteryAccessory::subscribeBatteryLevelState,
21+
batteryAccessory::unsubscribeBatteryLevelState
22+
));
23+
}
1324
}
1425
}

0 commit comments

Comments
 (0)