Skip to content

Commit f5bf9a0

Browse files
authored
'ToBooleanObservable' will now treat all states other than IsOn as false. This means observables will emit even if an entity is removed, unavailable, or unknown. (#234)
* 'ToBooleanObservable' will now treat all states other than `IsOn` as false. This means observables will emit even if an entity is removed, unavailable, or unknown. * Fixed unit tests.
1 parent 0bfa4cb commit f5bf9a0

2 files changed

Lines changed: 30 additions & 46 deletions

File tree

src/CodeCasa.NetDaemon.Extensions.Observables/EntityExtensions.ToBooleanObservable.cs

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,46 @@ public static partial class EntityExtensions
77
{
88
/// <summary>
99
/// <para>
10-
/// Returns a boolean observable that emits true when the entity opens and emits false when the entity closes.
11-
/// The observable is distinct until changed. Other state changes are ignored.
10+
/// Returns a boolean observable that emits <see langword="true"/> when the entity opens
11+
/// and emits <see langword="false"/> when the entity closes or changes to any other state.
12+
/// The observable is distinct until changed.
1213
/// </para>
1314
/// <para>
14-
/// State changes other than open or closed (on or off on the entity) are ignored. This also includes a null entity state. This is typically received when an entity is removed. This will not be emitted in the observable.
15+
/// Any state other than "on" (such as off, unknown, unavailable, or a null state when
16+
/// the entity is removed) is treated as closed and will emit <see langword="false"/>.
1517
/// </para>
1618
/// </summary>
1719
public static IObservable<bool> ToOpenClosedObservable(this Entity entity) => entity.ToBooleanObservable();
1820

1921
/// <summary>
2022
/// <para>
21-
/// Returns a boolean observable that emits true when the entity turns on and emits false when the entity turns off.
22-
/// The observable is distinct until changed. Other state changes are ignored.
23+
/// Returns a boolean observable that emits <see langword="true"/> when the entity turns on
24+
/// and emits <see langword="false"/> when the entity turns off or changes to any other state.
25+
/// The observable is distinct until changed.
2326
/// </para>
2427
/// <para>
25-
/// State changes other than on or off are ignored. This also includes a null entity state. This is typically received when an entity is removed. This will not be emitted in the observable.
28+
/// Any state other than "on" (such as off, unknown, unavailable, or a null state when
29+
/// the entity is removed) is treated as off and will emit <see langword="false"/>.
2630
/// </para>
2731
/// </summary>
2832
public static IObservable<bool> ToOnOffObservable(this Entity entity) => entity.ToBooleanObservable();
2933

3034
/// <summary>
3135
/// <para>
32-
/// Returns a boolean observable that emits true when the entity turns on and emits false when the entity turns off.
33-
/// The observable is distinct until changed. Other state changes are ignored.
36+
/// Returns a boolean observable that emits true when the entity turns on and emits false when the entity changes to any other state (including off, unknown, unavailable or null).
37+
/// The observable is distinct until changed.
3438
/// </para>
3539
/// <para>
36-
/// State changes other than on or off are ignored. This also includes a null entity state. This is typically received when an entity is removed. This will not be emitted in the observable.
40+
/// A null entity state, which typically indicates the entity has been removed, will emit false.
3741
/// </para>
3842
/// </summary>
3943
public static IObservable<bool> ToBooleanObservable(this Entity entity)
4044
{
4145
ArgumentNullException.ThrowIfNull(entity);
4246

43-
var statefulObservable = entity.Stateful();
44-
45-
var trueObservable =
46-
statefulObservable
47-
.Where(s => s.New?.IsOn() ?? false)
48-
.Select(_ => true);
49-
50-
var falseObservable =
51-
statefulObservable
52-
.Where(s => s.New?.IsOff() ?? false)
53-
.Select(_ => false);
54-
55-
return trueObservable.Merge(falseObservable).DistinctUntilChanged();
47+
return entity.Stateful()
48+
.Select(s => s.New?.IsOn() ?? false)
49+
.DistinctUntilChanged();
5650
}
5751

5852
/// <summary>
@@ -97,31 +91,21 @@ public static IObservable<bool>
9791

9892
/// <summary>
9993
/// <para>
100-
/// Returns a boolean observable that emits true when the entity turns on and emits false when the entity turns off.
94+
/// Returns a boolean observable that emits true when the entity turns on and emits false when the entity changes to any other state (including off, unknown, unavailable or null).
10195
/// Predicate will be evaluated on all state changes, including attribute changes.
102-
/// The observable only emits changes and will not emit the initial state.
103-
/// The observable is distinct until changed. Other state changes are ignored.
10496
/// </para>
10597
/// <para>
106-
/// State changes other than on or off are ignored. This also includes a null entity state. This is typically received when an entity is removed. This will not be emitted in the observable.
98+
/// The observable only emits subsequent changes and will not emit the initial state.
99+
/// A null entity state, which typically indicates the entity has been removed, will emit false.
107100
/// </para>
108101
/// </summary>
109102
public static IObservable<bool> ToChangesOnlyBooleanObservable(this Entity entity)
110103
{
111104
ArgumentNullException.ThrowIfNull(entity);
112105

113-
var statefulObservable = entity.StateAllChanges();
114-
var trueObservable =
115-
statefulObservable
116-
.Where(s => s.New?.IsOn() ?? false)
117-
.Select(_ => true);
118-
119-
var falseObservable =
120-
statefulObservable
121-
.Where(s => s.New?.IsOff() ?? false)
122-
.Select(_ => false);
123-
124-
return trueObservable.Merge(falseObservable).DistinctUntilChanged();
106+
return entity.StateAllChanges()
107+
.Select(s => s.New?.IsOn() ?? false)
108+
.DistinctUntilChanged();
125109
}
126110

127111
/// <summary>

tests/CodeCasa.NetDaemon.Extensions.Observables.Tests/EntityExtensions.ToBooleanObservable.Entity.Tests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public void ToBooleanObservable_Distinct()
103103
}
104104

105105
[TestMethod]
106-
public void ToBooleanObservable_OtherStatesAreIgnored()
106+
public void ToBooleanObservable_OtherStates_ReturnFalse()
107107
{
108108
// Arrange
109109
var results = new List<bool>();
@@ -113,11 +113,11 @@ public void ToBooleanObservable_OtherStatesAreIgnored()
113113
ChangeEntityState("Something else");
114114

115115
// Assert
116-
CollectionAssert.AreEqual(new[] { true }, results);
116+
CollectionAssert.AreEqual(new[] { true, false }, results);
117117
}
118118

119119
[TestMethod]
120-
public void ToBooleanObservable_NullIgnored()
120+
public void ToBooleanObservable_NullReturnsFalse()
121121
{
122122
// Arrange
123123
var results = new List<bool>();
@@ -127,7 +127,7 @@ public void ToBooleanObservable_NullIgnored()
127127
EntityStateNull();
128128

129129
// Assert
130-
CollectionAssert.AreEqual(new[] { true }, results);
130+
CollectionAssert.AreEqual(new[] { true, false }, results);
131131
}
132132

133133
[TestMethod]
@@ -244,7 +244,7 @@ public void ToChangesOnlyBooleanObservable_Distinct()
244244
}
245245

246246
[TestMethod]
247-
public void ToChangesOnlyBooleanObservable_OtherStatesAreIgnored()
247+
public void ToChangesOnlyBooleanObservable_OtherStates_ReturnFalse()
248248
{
249249
// Arrange
250250
var results = new List<bool>();
@@ -254,11 +254,11 @@ public void ToChangesOnlyBooleanObservable_OtherStatesAreIgnored()
254254
ChangeEntityState("Something else");
255255

256256
// Assert
257-
Assert.IsEmpty(results);
257+
CollectionAssert.AreEqual(new[] { false }, results);
258258
}
259259

260260
[TestMethod]
261-
public void ToChangesOnlyBooleanObservable_NullIgnored()
261+
public void ToChangesOnlyBooleanObservable_NullReturnsFalse()
262262
{
263263
// Arrange
264264
var results = new List<bool>();
@@ -268,7 +268,7 @@ public void ToChangesOnlyBooleanObservable_NullIgnored()
268268
EntityStateNull();
269269

270270
// Assert
271-
Assert.IsEmpty(results);
271+
CollectionAssert.AreEqual(new[] { false }, results);
272272
}
273273

274274
[TestMethod]

0 commit comments

Comments
 (0)