Skip to content

Commit 39b7182

Browse files
authored
Merge pull request #14 from gdombiak/master
Added support for battery levels.
2 parents ca24bb1 + f4eef87 commit 39b7182

19 files changed

+167
-54
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/AbstractServiceImpl.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,62 @@
11
package com.beowulfe.hap.impl.services;
22

3+
import com.beowulfe.hap.HomekitAccessory;
4+
import com.beowulfe.hap.Service;
5+
import com.beowulfe.hap.accessories.BatteryAccessory;
6+
import com.beowulfe.hap.characteristics.Characteristic;
7+
import com.beowulfe.hap.impl.characteristics.common.BatteryLevelCharacteristic;
8+
import com.beowulfe.hap.impl.characteristics.common.Name;
9+
310
import java.util.Collections;
411
import java.util.LinkedList;
512
import java.util.List;
613

7-
import com.beowulfe.hap.Service;
8-
import com.beowulfe.hap.characteristics.Characteristic;
9-
1014
abstract class AbstractServiceImpl implements Service {
1115

1216
private final String type;
1317
private final List<Characteristic> characteristics = new LinkedList<>();
14-
18+
19+
/**
20+
* This constructor has been deprecated and replaced with {@link #AbstractServiceImpl(String, HomekitAccessory)}.
21+
* Usages of this constructor will need to manually configure {@link Name} characteristic and
22+
* {@link BatteryLevelCharacteristic} if needed.
23+
*
24+
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
25+
*/
26+
@Deprecated
1527
public AbstractServiceImpl(String type) {
28+
this(type, null);
29+
}
30+
31+
/**
32+
* <p>Creates a new instance of this class with the specified UUID and {@link HomekitAccessory}.
33+
* Download and install <i>HomeKit Accessory Simulator</i> to discover the corresponding UUID for
34+
* the specific service.</p>
35+
*
36+
* <p>The new service will automatically add {@link Name} characteristic. If the accessory
37+
* is battery operated then it must implement {@link BatteryAccessory} and {@link BatteryLevelCharacteristic}
38+
* will be added too.</p>
39+
*
40+
* @param type unique UUID of the service. This information can be obtained from HomeKit Accessory Simulator.
41+
* @param accessory HomeKit accessory exposed as a service.
42+
*/
43+
public AbstractServiceImpl(String type, HomekitAccessory accessory) {
1644
this.type = type;
45+
46+
if (accessory != null) {
47+
// Add name characteristic
48+
addCharacteristic(new Name(accessory));
49+
50+
// If battery operated accessory then add BatteryLevelCharacteristic
51+
if (accessory instanceof BatteryAccessory) {
52+
BatteryAccessory batteryAccessory = (BatteryAccessory) accessory;
53+
addCharacteristic(new BatteryLevelCharacteristic(
54+
batteryAccessory::getBatteryLevelState,
55+
batteryAccessory::subscribeBatteryLevelState,
56+
batteryAccessory::unsubscribeBatteryLevelState
57+
));
58+
}
59+
}
1760
}
1861

1962
@Override

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

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

33
import com.beowulfe.hap.HomekitAccessory;
4-
import com.beowulfe.hap.impl.characteristics.common.Name;
54
import com.beowulfe.hap.impl.characteristics.information.Identify;
65
import com.beowulfe.hap.impl.characteristics.information.Manufacturer;
76
import com.beowulfe.hap.impl.characteristics.information.Model;
@@ -10,8 +9,7 @@
109
public class AccessoryInformationService extends AbstractServiceImpl {
1110

1211
public AccessoryInformationService(HomekitAccessory accessory) throws Exception {
13-
super("0000003E-0000-1000-8000-0026BB765291");
14-
addCharacteristic(new Name(accessory));
12+
super("0000003E-0000-1000-8000-0026BB765291", accessory);
1513
addCharacteristic(new Manufacturer(accessory));
1614
addCharacteristic(new Model(accessory));
1715
addCharacteristic(new SerialNumber(accessory));
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
package com.beowulfe.hap.impl.services;
22

33
import com.beowulfe.hap.accessories.ContactSensor;
4-
import com.beowulfe.hap.impl.characteristics.common.Name;
54
import com.beowulfe.hap.impl.characteristics.contactsensor.ContactSensorStateCharacteristic;
65

76
public class ContactSensorService extends AbstractServiceImpl {
87

98
public ContactSensorService(ContactSensor contactSensor) {
10-
super("00000080-0000-1000-8000-0026BB765291");
11-
addCharacteristic(new Name(contactSensor));
9+
super("00000080-0000-1000-8000-0026BB765291", contactSensor);
1210
addCharacteristic(new ContactSensorStateCharacteristic(contactSensor));
1311
}
1412
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package com.beowulfe.hap.impl.services;
22

33
import com.beowulfe.hap.accessories.Fan;
4-
import com.beowulfe.hap.impl.characteristics.common.Name;
54
import com.beowulfe.hap.impl.characteristics.common.PowerStateCharacteristic;
65
import com.beowulfe.hap.impl.characteristics.fan.RotationDirectionCharacteristic;
76
import com.beowulfe.hap.impl.characteristics.fan.RotationSpeedCharacteristic;
87

98
public class FanService extends AbstractServiceImpl {
109

1110
public FanService(Fan fan) {
12-
super("00000040-0000-1000-8000-0026BB765291");
13-
addCharacteristic(new Name(fan));
11+
super("00000040-0000-1000-8000-0026BB765291", fan);
1412
addCharacteristic(new PowerStateCharacteristic(
1513
() -> fan.getFanPower(),
1614
v -> fan.setFanPower(v),

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package com.beowulfe.hap.impl.services;
22

33
import com.beowulfe.hap.accessories.GarageDoor;
4-
import com.beowulfe.hap.impl.characteristics.common.Name;
54
import com.beowulfe.hap.impl.characteristics.common.ObstructionDetectedCharacteristic;
65
import com.beowulfe.hap.impl.characteristics.garage.CurrentDoorStateCharacteristic;
76
import com.beowulfe.hap.impl.characteristics.garage.TargetDoorStateCharacteristic;
87

98
public class GarageDoorService extends AbstractServiceImpl {
109

1110
public GarageDoorService(GarageDoor door) {
12-
super("00000041-0000-1000-8000-0026BB765291");
13-
addCharacteristic(new Name(door));
11+
super("00000041-0000-1000-8000-0026BB765291", door);
1412
addCharacteristic(new CurrentDoorStateCharacteristic(door));
1513
addCharacteristic(new TargetDoorStateCharacteristic(door));
1614
addCharacteristic(new ObstructionDetectedCharacteristic(() -> door.getObstructionDetected(),

0 commit comments

Comments
 (0)