27
27
import oly .netpowerctrl .scenes .SceneCollection ;
28
28
import oly .netpowerctrl .scenes .SceneItem ;
29
29
import oly .netpowerctrl .timer .TimerController ;
30
- import oly .netpowerctrl .utils .ShowToast ;
30
+ import oly .netpowerctrl .utils .notifications . InAppNotifications ;
31
31
32
32
/**
33
33
* Device Updates go into this object and are propagated to all observers and the device collection.
@@ -40,7 +40,7 @@ public class AppData {
40
40
public static final DataQueryCompletedObserver observersDataQueryCompleted = new DataQueryCompletedObserver ();
41
41
public static final DataLoadedObserver observersOnDataLoaded = new DataLoadedObserver ();
42
42
public static final NewDeviceObserver observersNew = new NewDeviceObserver ();
43
- private static final String TAG = AppData . class . getName () ;
43
+ private static final String TAG = " AppData" ;
44
44
45
45
public final List <Device > newDevices = new ArrayList <>();
46
46
final public DeviceCollection deviceCollection = new DeviceCollection ();
@@ -127,7 +127,6 @@ public Set<Integer> getAllReceivePorts() {
127
127
* @param deviceObserverBase The DeviceObserver
128
128
*/
129
129
public void removeUpdateDeviceState (DeviceObserverBase deviceObserverBase ) {
130
- Log .w ("DeviceQuery" , "remove" );
131
130
updateDeviceStateList .remove (deviceObserverBase );
132
131
}
133
132
@@ -148,11 +147,23 @@ public void addUpdateDeviceState(DeviceObserverBase deviceObserverBase) {
148
147
* @param source Source device that has been updated
149
148
*/
150
149
private void notifyDeviceQueries (Device source ) {
150
+ List <DeviceObserverBase > deviceObserverBaseList = new ArrayList <>();
151
+
151
152
Iterator <DeviceObserverBase > it = updateDeviceStateList .iterator ();
152
153
while (it .hasNext ()) {
153
154
// Return true if the DeviceQuery object has finished its task.
154
- if (it .next ().notifyObservers (source ))
155
+ DeviceObserverBase deviceObserverBase = it .next ();
156
+ if (deviceObserverBase .notifyObservers (source )) {
155
157
it .remove ();
158
+ deviceObserverBaseList .add (deviceObserverBase );
159
+ }
160
+ }
161
+
162
+ // Handle all finished device observers now. We have to split the finishing operation
163
+ // and updateDeviceStateList iteration because finishWithTimeouts may cause that that this
164
+ // method is called again and would lead to a concurrent access violation otherwise.
165
+ for (DeviceObserverBase deviceObserverBase : deviceObserverBaseList ) {
166
+ deviceObserverBase .finishWithTimeouts ();
156
167
}
157
168
}
158
169
@@ -248,13 +259,16 @@ public void onDeviceErrorByName(Context context, String name, String errMessage)
248
259
Iterator <DeviceObserverBase > it = updateDeviceStateList .iterator ();
249
260
while (it .hasNext ()) {
250
261
// Return true if the DeviceQuery object has finished its task.
251
- if (it .next ().notifyObservers (name ))
262
+ DeviceObserverBase deviceObserverBase = it .next ();
263
+ if (deviceObserverBase .notifyObservers (name )) {
252
264
it .remove ();
265
+ deviceObserverBase .finishWithTimeouts ();
266
+ }
253
267
}
254
268
255
269
// error packet received
256
270
String error = context .getString (R .string .error_packet_received ) + ": " + errMessage ;
257
- ShowToast .FromOtherThread (context , error );
271
+ InAppNotifications .FromOtherThread (context , error );
258
272
}
259
273
260
274
public int getReachableConfiguredDevices () {
@@ -354,6 +368,12 @@ public void execute(Scene scene, onExecutionFinished callback) {
354
368
public void execute (final DevicePort port , final int command , final onExecutionFinished callback ) {
355
369
PluginInterface remote = port .device .getPluginInterface ();
356
370
if (remote != null ) {
371
+ // mark device as changed. Slaves (see below) will also enter this method and will be
372
+ // marked as changed. This is necessary for this scenario: The slave is already in the target state
373
+ // but will be marked as currently-executed (progressbar is visible). Because an update of the device
374
+ // will not be propagated because nothing actually changed, this currently-executed state will
375
+ // stay indefinitely. Therefore we mark all currently-executed devices as changed here.
376
+ port .device .setHasChanged ();
357
377
remote .execute (port , command , callback );
358
378
359
379
// Support for slaves of an outlet.
@@ -369,7 +389,7 @@ else if (command == DevicePort.TOGGLE)
369
389
370
390
for (UUID slave_uuid : slaves ) {
371
391
DevicePort p = getInstance ().findDevicePort (slave_uuid );
372
- if (p != null )
392
+ if (p != null && p != port )
373
393
execute (p , bValue ? DevicePort .ON : DevicePort .OFF , null );
374
394
}
375
395
}
0 commit comments