44import com .beowulfe .hap .impl .http .HomekitClientConnection ;
55import com .beowulfe .hap .impl .http .HttpResponse ;
66import com .beowulfe .hap .impl .json .EventController ;
7+ import java .util .ArrayList ;
78import java .util .Collections ;
89import java .util .Iterator ;
910import java .util .Set ;
@@ -20,6 +21,9 @@ public class SubscriptionManager {
2021 new ConcurrentHashMap <>();
2122 private final ConcurrentMap <HomekitClientConnection , Set <EventableCharacteristic >> reverse =
2223 new ConcurrentHashMap <>();
24+ private final ConcurrentMap <HomekitClientConnection , ArrayList <PendingNotification >>
25+ pendingNotifications = new ConcurrentHashMap <>();
26+ private int nestedBatches = 0 ;
2327
2428 public synchronized void addSubscription (
2529 int aid ,
@@ -72,6 +76,7 @@ public synchronized void removeSubscription(
7276
7377 public synchronized void removeConnection (HomekitClientConnection connection ) {
7478 Set <EventableCharacteristic > characteristics = reverse .remove (connection );
79+ pendingNotifications .remove (connection );
7580 if (characteristics != null ) {
7681 for (EventableCharacteristic characteristic : characteristics ) {
7782 Set <HomekitClientConnection > characteristicSubscriptions =
@@ -91,10 +96,42 @@ private <T> Set<T> newSet() {
9196 return Collections .newSetFromMap (new ConcurrentHashMap <T , Boolean >());
9297 }
9398
94- public void publish (int accessoryId , int iid , EventableCharacteristic changed ) {
99+ public synchronized void batchUpdate () {
100+ ++this .nestedBatches ;
101+ }
102+
103+ public synchronized void completeUpdateBatch () {
104+ if (--this .nestedBatches == 0 && !pendingNotifications .isEmpty ()) {
105+ LOGGER .info ("Publishing batched changes" );
106+ for (ConcurrentMap .Entry <HomekitClientConnection , ArrayList <PendingNotification >> entry :
107+ pendingNotifications .entrySet ()) {
108+ try {
109+ HttpResponse message = new EventController ().getMessage (entry .getValue ());
110+ entry .getKey ().outOfBand (message );
111+ } catch (Exception e ) {
112+ LOGGER .error ("Faled to create new event message" , e );
113+ }
114+ }
115+ pendingNotifications .clear ();
116+ }
117+ }
118+
119+ public synchronized void publish (int accessoryId , int iid , EventableCharacteristic changed ) {
120+ if (nestedBatches != 0 ) {
121+ LOGGER .info ("Batching change for " + accessoryId );
122+ PendingNotification notification = new PendingNotification (accessoryId , iid , changed );
123+ for (HomekitClientConnection connection : subscriptions .get (changed )) {
124+ if (!pendingNotifications .containsKey (connection )) {
125+ pendingNotifications .put (connection , new ArrayList <PendingNotification >());
126+ }
127+ pendingNotifications .get (connection ).add (notification );
128+ }
129+ return ;
130+ }
131+
95132 try {
96133 HttpResponse message = new EventController ().getMessage (accessoryId , iid , changed );
97- LOGGER .info ("Publishing changes for " + accessoryId );
134+ LOGGER .info ("Publishing change for " + accessoryId );
98135 for (HomekitClientConnection connection : subscriptions .get (changed )) {
99136 connection .outOfBand (message );
100137 }
0 commit comments