Skip to content

Commit 4f1404d

Browse files
author
Eugen Freiter
committed
add smart speaker
Signed-off-by: Eugen Freiter <[email protected]>
1 parent 18f6442 commit 4f1404d

File tree

8 files changed

+315
-4
lines changed

8 files changed

+315
-4
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package io.github.hapjava.accessories;
2+
3+
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
4+
import io.github.hapjava.characteristics.impl.television.CurrentMediaStateEnum;
5+
import io.github.hapjava.characteristics.impl.television.TargetMediaStateEnum;
6+
import io.github.hapjava.services.Service;
7+
import io.github.hapjava.services.impl.SmartSpeakerService;
8+
import java.util.Collection;
9+
import java.util.Collections;
10+
import java.util.concurrent.CompletableFuture;
11+
12+
/** Smart Speaker accessory. */
13+
public interface SmartSpeakerAccessory extends HomekitAccessory {
14+
15+
/**
16+
* Retrieves the current media state (see {@link
17+
* io.github.hapjava.characteristics.impl.television.CurrentMediaStateEnum} for supported values).
18+
*
19+
* @return a future that will contain the current media state
20+
*/
21+
CompletableFuture<CurrentMediaStateEnum> getCurrentMediaState();
22+
23+
/**
24+
* Subscribes to changes in the current media state.
25+
*
26+
* @param callback the function to call when the current media state changes.
27+
*/
28+
void subscribeCurrentMediaState(HomekitCharacteristicChangeCallback callback);
29+
30+
/** Unsubscribes from changes in the current media state. */
31+
void unsubscribeCurrentMediaState();
32+
33+
/**
34+
* Retrieves the target media state (see {@link TargetMediaStateEnum} for supported values).
35+
*
36+
* @return a future that will contain the target media state
37+
*/
38+
CompletableFuture<TargetMediaStateEnum> getTargetMediaState();
39+
40+
/**
41+
* Set the target media state (see {@link TargetMediaStateEnum} for supported values).
42+
*
43+
* @param targetMediaState target media state
44+
* @return a future that completes when the change is made
45+
*/
46+
CompletableFuture<Void> setTargetMediaState(TargetMediaStateEnum targetMediaState);
47+
48+
/**
49+
* Subscribes to changes in the target media state.
50+
*
51+
* @param callback the function to call when the target media state changes.
52+
*/
53+
void subscribeTargetMediaState(HomekitCharacteristicChangeCallback callback);
54+
55+
/** Unsubscribes from changes in the target media state. */
56+
void unsubscribeTargetMediaState();
57+
58+
@Override
59+
default Collection<Service> getServices() {
60+
return Collections.singleton(new SmartSpeakerService(this));
61+
}
62+
}

src/main/java/io/github/hapjava/accessories/TelevisionAccessory.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public interface TelevisionAccessory extends HomekitAccessory {
7272
CompletableFuture<String> getConfiguredName();
7373

7474
/**
75-
* Sets the mute status
75+
* Sets the configured name
7676
*
7777
* @param name configured name
7878
* @return a future that completes when the change is made
@@ -81,13 +81,13 @@ public interface TelevisionAccessory extends HomekitAccessory {
8181
CompletableFuture<Void> setConfiguredName(String name) throws Exception;
8282

8383
/**
84-
* Subscribes to changes in mute state.
84+
* Subscribes to changes in configured name.
8585
*
86-
* @param callback the function to call when the state changes.
86+
* @param callback the function to call when the configureed name changes.
8787
*/
8888
void subscribeConfiguredName(HomekitCharacteristicChangeCallback callback);
8989

90-
/** Unsubscribes from changes in the mute state. */
90+
/** Unsubscribes from changes in the configured name state. */
9191
void unsubscribeConfiguredName();
9292

9393
/**
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.github.hapjava.accessories.optionalcharacteristic;
2+
3+
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
4+
import java.util.concurrent.CompletableFuture;
5+
6+
/**
7+
* Accessory with AirPlay enable characteristic {@link
8+
* io.github.hapjava.characteristics.impl.common.AirPlayEnableCharacteristic}.
9+
*/
10+
public interface AccessoryWithAirPlayEnable {
11+
12+
/**
13+
* Retrieves the AirPlay enable state
14+
*
15+
* @return a future that will contain the AirPlay enable state.
16+
*/
17+
CompletableFuture<Integer> getAirPlayEnable();
18+
19+
/**
20+
* Sets the AirPlay enable state
21+
*
22+
* @param state AirPlay enable state
23+
* @return a future that completes when the AirPlay enable is changed
24+
* @throws Exception when the AirPlay enable cannot be set
25+
*/
26+
CompletableFuture<Void> setAirPlayEnable(Integer state) throws Exception;
27+
28+
/**
29+
* Subscribes to changes in the AirPlay enable state.
30+
*
31+
* @param callback the function to call when the AirPlay enable state changes.
32+
*/
33+
void subscribeAirPlayEnable(HomekitCharacteristicChangeCallback callback);
34+
35+
/** Unsubscribes from changes in the AirPlay enable state. */
36+
void unsubscribeAirPlayEnable();
37+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.github.hapjava.accessories.optionalcharacteristic;
2+
3+
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
4+
import java.util.concurrent.CompletableFuture;
5+
6+
/** Accessory with configured name. */
7+
public interface AccessoryWithConfiguredName {
8+
9+
/**
10+
* Retrieves configured name.
11+
*
12+
* @return configured name
13+
*/
14+
CompletableFuture<String> getConfiguredName();
15+
16+
/**
17+
* Sets the configured name
18+
*
19+
* @param name configured name
20+
* @return a future that completes when the change is made
21+
* @throws Exception when the change cannot be made
22+
*/
23+
CompletableFuture<Void> setConfiguredName(String name) throws Exception;
24+
25+
/**
26+
* Subscribes to changes in configured name.
27+
*
28+
* @param callback the function to call when the configureed name changes.
29+
*/
30+
void subscribeConfiguredName(HomekitCharacteristicChangeCallback callback);
31+
32+
/** Unsubscribes from changes in the configured name state. */
33+
void unsubscribeConfiguredName();
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.github.hapjava.accessories.optionalcharacteristic;
2+
3+
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
4+
import java.util.concurrent.CompletableFuture;
5+
6+
/**
7+
* Accessory with mute characteristic {@link
8+
* io.github.hapjava.characteristics.impl.audio.MuteCharacteristic}.
9+
*/
10+
public interface AccessoryWithMute {
11+
12+
/**
13+
* Retrieves mute status.
14+
*
15+
* @return true if accessory is muted
16+
*/
17+
CompletableFuture<Boolean> isMuted();
18+
19+
/**
20+
* Sets the mute status
21+
*
22+
* @param mute true if accessory should be muted
23+
* @return a future that completes when the change is made
24+
* @throws Exception when the change cannot be made
25+
*/
26+
CompletableFuture<Void> setMute(boolean mute) throws Exception;
27+
28+
/**
29+
* Subscribes to changes in mute state.
30+
*
31+
* @param callback the function to call when the state changes.
32+
*/
33+
void subscribeMuteState(HomekitCharacteristicChangeCallback callback);
34+
35+
/** Unsubscribes from changes in the mute state. */
36+
void unsubscribeMuteState();
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.github.hapjava.characteristics.impl.common;
2+
3+
import io.github.hapjava.characteristics.EventableCharacteristic;
4+
import io.github.hapjava.characteristics.ExceptionalConsumer;
5+
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
6+
import io.github.hapjava.characteristics.impl.base.IntegerCharacteristic;
7+
import java.util.Optional;
8+
import java.util.concurrent.CompletableFuture;
9+
import java.util.function.Consumer;
10+
import java.util.function.Supplier;
11+
12+
/** characteristic to control air play. */
13+
public class AirPlayEnableCharacteristic extends IntegerCharacteristic
14+
implements EventableCharacteristic {
15+
16+
public AirPlayEnableCharacteristic(
17+
Supplier<CompletableFuture<Integer>> getter,
18+
ExceptionalConsumer<Integer> setter,
19+
Consumer<HomekitCharacteristicChangeCallback> subscriber,
20+
Runnable unsubscriber) {
21+
super(
22+
"0000025B-0000-1000-8000-0026BB765291",
23+
"AirPlay enable",
24+
0,
25+
1,
26+
"",
27+
Optional.of(getter),
28+
Optional.of(setter),
29+
Optional.of(subscriber),
30+
Optional.of(unsubscriber));
31+
}
32+
}

src/main/java/io/github/hapjava/services/impl/DoorService.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import io.github.hapjava.accessories.DoorAccessory;
44
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithHoldPosition;
5+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithMute;
56
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithName;
67
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithObstructionDetection;
8+
import io.github.hapjava.characteristics.impl.audio.MuteCharacteristic;
79
import io.github.hapjava.characteristics.impl.common.NameCharacteristic;
810
import io.github.hapjava.characteristics.impl.common.ObstructionDetectedCharacteristic;
911
import io.github.hapjava.characteristics.impl.windowcovering.CurrentPositionCharacteristic;
@@ -53,6 +55,14 @@ public DoorService(DoorAccessory accessory) {
5355
((AccessoryWithObstructionDetection) accessory)::subscribeObstructionDetected,
5456
((AccessoryWithObstructionDetection) accessory)::unsubscribeObstructionDetected));
5557
}
58+
if (accessory instanceof AccessoryWithMute) {
59+
addOptionalCharacteristic(
60+
new MuteCharacteristic(
61+
((AccessoryWithMute) accessory)::isMuted,
62+
((AccessoryWithMute) accessory)::setMute,
63+
((AccessoryWithMute) accessory)::subscribeMuteState,
64+
((AccessoryWithMute) accessory)::unsubscribeMuteState));
65+
}
5666
}
5767

5868
public void addOptionalCharacteristic(NameCharacteristic name) {
@@ -67,4 +77,8 @@ public void addOptionalCharacteristic(
6777
ObstructionDetectedCharacteristic obstructionDetectedCharacteristic) {
6878
addCharacteristic(obstructionDetectedCharacteristic);
6979
}
80+
81+
public void addOptionalCharacteristic(MuteCharacteristic muteCharacteristic) {
82+
addCharacteristic(muteCharacteristic);
83+
}
7084
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package io.github.hapjava.services.impl;
2+
3+
import io.github.hapjava.accessories.SmartSpeakerAccessory;
4+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithAirPlayEnable;
5+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithConfiguredName;
6+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithMute;
7+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithName;
8+
import io.github.hapjava.accessories.optionalcharacteristic.AccessoryWithVolume;
9+
import io.github.hapjava.characteristics.impl.audio.MuteCharacteristic;
10+
import io.github.hapjava.characteristics.impl.audio.VolumeCharacteristic;
11+
import io.github.hapjava.characteristics.impl.common.AirPlayEnableCharacteristic;
12+
import io.github.hapjava.characteristics.impl.common.ConfiguredNameCharacteristic;
13+
import io.github.hapjava.characteristics.impl.common.NameCharacteristic;
14+
import io.github.hapjava.characteristics.impl.television.CurrentMediaStateCharacteristic;
15+
import io.github.hapjava.characteristics.impl.television.TargetMediaStateCharacteristic;
16+
17+
/** A smart speaker service can be used to control the audio output settings on a speaker device. */
18+
public class SmartSpeakerService extends AbstractServiceImpl {
19+
20+
public SmartSpeakerService(
21+
CurrentMediaStateCharacteristic currentMediaStateCharacteristic,
22+
TargetMediaStateCharacteristic targetMediaStateCharacteristic) {
23+
super("00000228-0000-1000-8000-0026BB765291");
24+
addCharacteristic(currentMediaStateCharacteristic);
25+
addCharacteristic(targetMediaStateCharacteristic);
26+
}
27+
28+
public SmartSpeakerService(SmartSpeakerAccessory accessory) {
29+
this(
30+
new CurrentMediaStateCharacteristic(
31+
accessory::getCurrentMediaState,
32+
accessory::subscribeCurrentMediaState,
33+
accessory::unsubscribeCurrentMediaState),
34+
new TargetMediaStateCharacteristic(
35+
accessory::getTargetMediaState,
36+
accessory::setTargetMediaState,
37+
accessory::subscribeTargetMediaState,
38+
accessory::unsubscribeTargetMediaState));
39+
if (accessory instanceof AccessoryWithName) {
40+
addOptionalCharacteristic(new NameCharacteristic(((AccessoryWithName) accessory)::getName));
41+
}
42+
if (accessory instanceof AccessoryWithVolume) {
43+
addOptionalCharacteristic(
44+
new VolumeCharacteristic(
45+
((AccessoryWithVolume) accessory)::getVolume,
46+
((AccessoryWithVolume) accessory)::setVolume,
47+
((AccessoryWithVolume) accessory)::subscribeVolume,
48+
((AccessoryWithVolume) accessory)::unsubscribeVolume));
49+
}
50+
if (accessory instanceof AccessoryWithConfiguredName) {
51+
addOptionalCharacteristic(
52+
new ConfiguredNameCharacteristic(
53+
((AccessoryWithConfiguredName) accessory)::getConfiguredName,
54+
((AccessoryWithConfiguredName) accessory)::setConfiguredName,
55+
((AccessoryWithConfiguredName) accessory)::subscribeConfiguredName,
56+
((AccessoryWithConfiguredName) accessory)::unsubscribeConfiguredName));
57+
}
58+
if (accessory instanceof AccessoryWithMute) {
59+
addOptionalCharacteristic(
60+
new MuteCharacteristic(
61+
((AccessoryWithMute) accessory)::isMuted,
62+
((AccessoryWithMute) accessory)::setMute,
63+
((AccessoryWithMute) accessory)::subscribeMuteState,
64+
((AccessoryWithMute) accessory)::unsubscribeMuteState));
65+
}
66+
if (accessory instanceof AccessoryWithAirPlayEnable) {
67+
addOptionalCharacteristic(
68+
new AirPlayEnableCharacteristic(
69+
((AccessoryWithAirPlayEnable) accessory)::getAirPlayEnable,
70+
((AccessoryWithAirPlayEnable) accessory)::setAirPlayEnable,
71+
((AccessoryWithAirPlayEnable) accessory)::subscribeAirPlayEnable,
72+
((AccessoryWithAirPlayEnable) accessory)::unsubscribeAirPlayEnable));
73+
}
74+
}
75+
76+
public void addOptionalCharacteristic(NameCharacteristic name) {
77+
addCharacteristic(name);
78+
}
79+
80+
public void addOptionalCharacteristic(VolumeCharacteristic volume) {
81+
addCharacteristic(volume);
82+
}
83+
84+
public void addOptionalCharacteristic(ConfiguredNameCharacteristic configuredNameCharacteristic) {
85+
addCharacteristic(configuredNameCharacteristic);
86+
}
87+
88+
public void addOptionalCharacteristic(MuteCharacteristic muteCharacteristic) {
89+
addCharacteristic(muteCharacteristic);
90+
}
91+
92+
public void addOptionalCharacteristic(AirPlayEnableCharacteristic airPlayEnableCharacteristic) {
93+
addCharacteristic(airPlayEnableCharacteristic);
94+
}
95+
}

0 commit comments

Comments
 (0)