public async Task TestGetReachableScenes() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/zone/getReachableScenes") .WithExactQueryString($"id=32027&groupID=1&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""reachableScenes"": [ 0, 5, 17, 18, 19 ], ""userSceneNames"": [] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await dsApiClient.GetReachableScenes(zoneKitchen, Color.Yellow); Assert.Equal(new List <int>() { 0, 5, 17, 18, 19 }.Select(x => (Scene)x), result.ReachableScenes); Assert.Equal(new List <string>(), result.UserSceneNames); }
public async Task TestGetSiteChargers() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockSonnenConnection.BaseUri}sites/{MockSonnenConnection.SiteId}/chargers") .Respond("application/json", @"{ ""data"": [ { ""id"": """ + MockSonnenConnection.ChargerId + @""", ""type"": ""chargers"", ""attributes"": { ""serial_number"": ""12345678"", ""vendor"": ""Etrel"", ""model"": ""G-HABCDEFGH-A00"", ""charge_point_id"": ""19998877"", ""default_charging_mode"": ""SMART"", ""default_departure_time"": ""06:00:00"", ""charging_authorization_type"": ""plug_and_charge"", ""charging_unit_type"": ""KW"", ""smartmode_paused"": true, ""max_current_model"": null, ""max_current_config"": null, ""last_seen_at"": null, ""websocket_token"": ""eyJh1234123412341234.eyJp1234123412341234123412341234123412341234.baPtf-eR1n6OyvXSpEbP8Q"" }, ""relationships"": { ""cars"": { ""links"": { ""related"": ""https://my-api.sonnen.de/v1/chargers/" + MockSonnenConnection.ChargerId + @"/cars"" } } }, ""links"": { ""self"": ""https://my-api.sonnen.de/v1/chargers/" + MockSonnenConnection.ChargerId + @""" } } ] }"); using var sonnenClient = new SonnenPortalClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await sonnenClient.GetSiteChargers(MockSonnenConnection.SiteId); Assert.NotNull(result); Assert.Single(result); Assert.Equal(MockSonnenConnection.ChargerId, result[0].Id); Assert.Equal("12345678", result[0].SerialNumber); Assert.Equal("Etrel", result[0].Vendor); Assert.Equal("G-HABCDEFGH-A00", result[0].Model); Assert.Equal("19998877", result[0].ChargePointId); Assert.Equal("SMART", result[0].DefaultChargingMode); Assert.Equal("06:00:00", result[0].DefaultDepartureTime); Assert.Equal("plug_and_charge", result[0].ChargingAuthorizationType); Assert.Equal("KW", result[0].ChargingUnitType); Assert.True(result[0].SmartmodePaused); Assert.Null(result[0].LastSeenAt); Assert.Equal("eyJh1234123412341234.eyJp1234123412341234123412341234123412341234.baPtf-eR1n6OyvXSpEbP8Q", result[0].WebsocketToken); }
public async Task TestGetDevicesAndOutputChannelTypes() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/property/query") .WithExactQueryString($"query=/apartment/zones/*(ZoneID)/devices/*(dSID)/outputChannels/*(id)&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""zones"": [ { ""ZoneID"": 32027, ""devices"": [ { ""dSID"": ""1337234200000e80deadbeef"", ""outputChannels"": [ { ""id"": ""brightness"" } ] }, { ""dSID"": ""4242000aaa000fa0deadbeef"", ""outputChannels"": [ { ""id"": ""shadePositionOutside"" } ] }, { ""dSID"": ""f00f000aaa000120beefbeef"", ""outputChannels"": [] } ] } ] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var zonesScenes = await dsApiClient.GetDevicesAndOutputChannelTypes(); Assert.NotEmpty(zonesScenes.Zones); Assert.Equal("brightness", zonesScenes.Zones[0].Devices[0].OutputChannels[0].Id); Assert.Equal("shadePositionOutside", zonesScenes.Zones[0].Devices[1].OutputChannels[0].Id); Assert.Empty(zonesScenes.Zones[0].Devices[2].OutputChannels); }
public async Task TestTwinTwoWaySync() { var mockHttp = new MockHttpMessageHandler(); mockHttp.AddInitialAndSubscribeMocks(); var callSceneRequest = mockHttp.AddCallSceneMock(zoneKitchen, Color.Yellow, SceneCommand.Preset2); var mockedEvent = mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/event/get") .WithExactQueryString($"subscriptionID=10&timeout=60000&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", SceneCommand.Preset0.ToMockedSceneEvent()); using (var twin = new DigitalstromDssTwin(mockHttp.AddAuthMock().ToMockProvider())) { await twin.WaitModelInitializedAsync(3); mockHttp.AutoFlush = false; try { mockHttp.Flush(); } catch { } // subscribe to twin changes of the yellow group in the kitchen var changedCount = 0; twin[zoneKitchen, Color.Yellow].PropertyChanged += (s, e) => { if (e.PropertyName == "Value") { changedCount++; } }; // the dss reports an event from outside the twin (maybe someone pressed a button, or called a scene via digitalstrom app) int changedCountBefore1 = changedCount; await mockHttp.MockDssEventAndWaitAsync(mockedEvent, twin, zoneKitchen, Color.Yellow, SceneCommand.Preset1); Assert.Equal((int)SceneCommand.Preset1, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.True(changedCount > changedCountBefore1); // programatically set a new scene on the twin, which should result in a CallScene api request await mockHttp.WaitForCallSceneAsync(callSceneRequest, () => { twin[zoneKitchen, Color.Yellow].Value = SceneCommand.Preset2; }); Assert.Equal((int)SceneCommand.Preset2, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.True(1 >= mockHttp.GetMatchCount(callSceneRequest)); // the called scene in turn results in a dss event that is fired back to the twin int changedCountBefore2 = changedCount; await mockHttp.MockDssEventAndWaitAsync(mockedEvent, twin, zoneKitchen, Color.Yellow, SceneCommand.Preset2); Assert.Equal((int)SceneCommand.Preset2, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.True(changedCount > changedCountBefore2); } }
public async Task TestCallScene() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/zone/callScene") .WithExactQueryString($"id=32027&groupID=1&sceneNumber=5&force=true&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); await dsApiClient.CallScene(zoneKitchen, Color.Yellow, SceneCommand.Preset1, true); }
public async Task TestSetTemperatureControlValues() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/zone/setTemperatureControlValues") .WithExactQueryString($"id=32027&Night=22&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""ok"": false, ""message"": ""Cannot set control values in current mode"" }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); await Assert.ThrowsAsync <IOException>(() => dsApiClient.SetTemperatureControlValues(zoneKitchen, null, null, 22)); }
public async Task TestGetChargerLiveState() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockSonnenConnection.BaseUri}chargers/{MockSonnenConnection.ChargerId}/live-state") .Respond("application/json", @"{ ""data"": { ""id"": """ + MockSonnenConnection.ChargerId + @""", ""type"": ""charger-live-states"", ""attributes"": { ""measured_at"": ""2020-05-23T01:02:03.000Z"", ""active_power"": 0.0, ""current"": 0.032, ""charge_speed_kmh"": 0.0, ""car"": ""CONNECTED"", ""status"": ""CHARGING"", ""max_charge_current"": 7.2, ""smartmode"": true, ""departure_at"": ""2020-05-23T12:00:00.000Z"", ""transaction_charged_km"": 17.1, ""total_charged_km"": 82.2, ""total_charged_energy"": 1234.56599999999, ""charging_behaviour"": ""FIRST_SCHEDULE"", ""charging_authorization_required"": false } } }"); using var sonnenClient = new SonnenPortalClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await sonnenClient.GetChargerLiveState(MockSonnenConnection.ChargerId); Assert.Equal(DateTime.Parse("2020-05-23T01:02:03.000Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal), result.MeasuredAt); Assert.Equal(0.0, result.ActivePower); Assert.Equal(0.032, result.Current); Assert.Equal(0.0, result.ChargeSpeedKmh); Assert.Equal("CONNECTED", result.Car); Assert.Equal("CHARGING", result.Status); Assert.Equal(7.2, result.MaxChargeCurrent); Assert.True(result.Smartmode); Assert.Equal(DateTime.Parse("2020-05-23T12:00:00.000Z", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal), result.DepartureAt); Assert.Equal(17.1, result.TransactionChargedKm); Assert.Equal(82.2, result.TotalChargedKm); Assert.Equal(1234.56599999999, result.TotalChargedEnergy); Assert.Equal("FIRST_SCHEDULE", result.ChargingBehaviour); Assert.False(result.ChargingAuthorizationRequired); }
public async Task TestGetZonesAndLastCalledScenes() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/property/query") .WithExactQueryString($"query=/apartment/zones/*(ZoneID)/groups/*(group,lastCalledScene)&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""zones"": [ { ""ZoneID"": 32027, ""groups"": [ { ""group"": 0, ""lastCalledScene"": 0 }, { ""group"": 1, ""lastCalledScene"": 0 }, { ""group"": 2, ""lastCalledScene"": 0 }, { ""group"": 3, ""lastCalledScene"": 0 }, { ""group"": 4, ""lastCalledScene"": 5 }, { ""group"": 5, ""lastCalledScene"": 0 }, { ""group"": 6, ""lastCalledScene"": 0 }, { ""group"": 7, ""lastCalledScene"": 0 }, { ""group"": 8, ""lastCalledScene"": 40 }, { ""group"": 9, ""lastCalledScene"": 0 }, { ""group"": 10, ""lastCalledScene"": 0 }, { ""group"": 11, ""lastCalledScene"": 0 }, { ""group"": 12, ""lastCalledScene"": 0 }, { ""group"": 48, ""lastCalledScene"": 0 } ] } ] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var zonesScenes = await dsApiClient.GetZonesAndLastCalledScenes(); Assert.NotEmpty(zonesScenes.Zones); Assert.Equal(5, (int)zonesScenes.Zones[0].Groups.First(g => g.Group == 4).LastCalledScene); Assert.Equal(40, (int)zonesScenes.Zones[0].Groups.First(g => g.Group == 8).LastCalledScene); }
public async Task TestGetTemperatureControlValues() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/apartment/getTemperatureControlValues") .WithExactQueryString($"token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""zones"": [ { ""id"": 1, ""name"": ""RoomWithoutControl"" }, { ""id"": 32027, ""name"": ""RoomWithControl"", ""Off"": 8, ""Comfort"": 21, ""Economy"": 20, ""NotUsed"": 18, ""Night"": 17, ""Holiday"": 16, ""Cooling"": 23, ""CoolingOff"": 35 } ] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await dsApiClient.GetTemperatureControlValues(); Assert.Equal(32027, (int)result.Zones[1].Id); Assert.Equal("RoomWithControl", result.Zones[1].Name); Assert.Equal(8, result.Zones[1].Off); Assert.Equal(21, result.Zones[1].Comfort); Assert.Equal(20, result.Zones[1].Economy); Assert.Null(result.Zones[0].Off); Assert.Null(result.Zones[0].Comfort); Assert.Null(result.Zones[0].Economy); }
public async Task TestTwinChangeOnCallSceneEvent() { var mockHttp = new MockHttpMessageHandler(); mockHttp.AddInitialAndSubscribeMocks(); var mockedEvent = mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/event/get") .WithExactQueryString($"subscriptionID=10&timeout=60000&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", SceneCommand.Preset0.ToMockedSceneEvent()); var callSceneRequest1 = mockHttp.AddCallSceneMock(zoneKitchen, Color.Yellow, SceneCommand.Preset1); using (var twin = new DigitalstromDssTwin(mockHttp.AddAuthMock().ToMockProvider())) { await twin.WaitModelInitializedAsync(3); mockHttp.AutoFlush = false; try { mockHttp.Flush(); } catch { } int numChangedEvents = 0; twin.SceneChanged += (s, e) => { numChangedEvents++; }; Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest1)); await mockHttp.MockDssEventAndWaitAsync(mockedEvent, twin, zoneKitchen, Color.Yellow, SceneCommand.Preset1); Assert.Equal((int)SceneCommand.Preset1, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest1)); Assert.True(1 <= numChangedEvents); // even firing a dss event with the same value again should result in a scene call (due to a new timestamp of the scene state) await mockHttp.MockDssEventAndWaitAsync(mockedEvent, twin, zoneKitchen, Color.Yellow, SceneCommand.Preset1); Assert.Equal((int)SceneCommand.Preset1, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest1)); Assert.True(2 <= numChangedEvents); await mockHttp.MockDssEventAndWaitAsync(mockedEvent, twin, zoneKitchen, Color.Yellow, SceneCommand.Preset2); Assert.Equal((int)SceneCommand.Preset2, (int)twin[zoneKitchen, Color.Yellow].Value); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest1)); Assert.True(3 <= numChangedEvents); } }
public async Task TestSceneCallOnTwinChange() { var mockHttp = new MockHttpMessageHandler(); mockHttp.AddInitialAndSubscribeMocks(); var callSceneRequest1 = mockHttp.AddCallSceneMock(zoneKitchen, Color.Yellow, SceneCommand.Preset1); var callSceneRequest2 = mockHttp.AddCallSceneMock(zoneKitchen, Color.Black, SceneCommand.DeepOff); using (var twin = new DigitalstromDssTwin(mockHttp.AddAuthMock().ToMockProvider())) { await twin.WaitModelInitializedAsync(2); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest1)); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest2)); await mockHttp.WaitForCallSceneAsync(callSceneRequest1, () => { twin[zoneKitchen, Color.Yellow].Value = SceneCommand.Preset1; }); Assert.Equal(1, mockHttp.GetMatchCount(callSceneRequest1)); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest2)); // even setting the same value again should result in a scene call await mockHttp.WaitForCallSceneAsync(callSceneRequest1, () => { twin[zoneKitchen, Color.Yellow].Value = SceneCommand.Preset1; }); Assert.Equal(2, mockHttp.GetMatchCount(callSceneRequest1)); Assert.Equal(0, mockHttp.GetMatchCount(callSceneRequest2)); await mockHttp.WaitForCallSceneAsync(callSceneRequest2, () => { twin[zoneKitchen, Color.Black].Value = SceneCommand.DeepOff; }); Assert.Equal(2, mockHttp.GetMatchCount(callSceneRequest1)); Assert.Equal(1, mockHttp.GetMatchCount(callSceneRequest2)); } }
public async Task TestGetLastCalledScene() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/zone/getLastCalledScene") .WithExactQueryString($"id=32027&groupID=1&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""scene"": 5 }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await dsApiClient.GetLastCalledScene(zoneKitchen, Color.Yellow); Assert.Equal(5, (int)(result.Scene ?? 0)); }
public async Task TestGetStructure() { var mockHttp = new MockHttpMessageHandler(); using var dsApiClient = new DigitalstromDssClient(mockHttp .AddAuthMock() .AddStructureMock() .ToMockProvider()); var result = await dsApiClient.GetStructure(); Assert.Equal("South - none", result.Clusters[0].Name); Assert.Equal(2, result.Clusters[0].ApplicationType); Assert.True(result.Clusters[0].IsPresent); Assert.Equal(32027, (int)result.Zones[0].Id); Assert.True(result.Zones[0].IsPresent); Assert.Equal("1337234200000e80deadbeef", result.Zones[0].Devices[0].Id); Assert.Equal("MyDevice", result.Zones[0].Devices[0].Name); Assert.Equal("13372342f800000000000f0000deadbeef", result.Zones[0].Devices[0].DSUID); Assert.Equal("99999942f800000000000f0000deadbeef", result.Zones[0].Devices[0].MeterDSUID); Assert.Equal(new DateTime(2019, 04, 19, 22, 33, 29), result.Zones[0].Devices[0].LastDiscovered); Assert.Equal(new List <int>() { 48 }.Select(x => (Group)x), result.Zones[0].Devices[0].Groups); Assert.Equal(253, (int)result.Zones[0].Devices[0].Sensors[0].Type); Assert.Equal(0, result.Zones[0].Devices[0].Sensors[0].Value); Assert.False(result.Zones[0].Devices[0].Sensors[0].Valid); Assert.Equal(3, (int)result.Zones[0].Groups[0].Color); Assert.True(result.Zones[0].Groups[0].IsValid); Assert.Equal(new List <int>() { 0, 5, 17, 18, 19, 6 }.Select(x => (Scene)x), result.Zones[0].Groups[0].ActiveBasicScenes); }
public async Task TestGetDevicesAndLastOutputValues() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/property/query") .WithExactQueryString($"query=/apartment/zones/*(ZoneID)/devices/*(dSID)/status(lastChanged)/outputs/*(value,targetValue)&token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""zones"": [ { ""ZoneID"": 32027, ""devices"": [ { ""dSID"": ""1337234200000e80deadbeef"", ""status"": [ { ""lastChanged"": ""\""2019-01-15T03:56:29.800Z\"""", ""outputs"": [ { ""value"": 0, ""targetValue"": 0 } ] } ] }, { ""dSID"": ""4242000aaa000fa0deadbeef"", ""status"": [ { ""lastChanged"": ""\""2019-01-18T17:15:30.249Z\"""", ""outputs"": [ { ""value"": 21.6404131546947, ""targetValue"": 21.6404131546947 } ] } ] }, { ""dSID"": ""f00f000aaa000120beefbeef"", ""status"": [] } ] } ] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var zonesScenes = await dsApiClient.GetDevicesAndLastOutputValues(); Assert.NotEmpty(zonesScenes.Zones); Assert.Equal(DateTime.Parse("2019-01-15T03:56:29.800Z"), zonesScenes.Zones[0].Devices[0].Status[0].LastChangedTime); Assert.Equal(0d, zonesScenes.Zones[0].Devices[0].Status[0].Outputs[0].Value); Assert.Equal(0d, zonesScenes.Zones[0].Devices[0].Status[0].Outputs[0].TargetValue); Assert.Equal(21.6404131546947d, zonesScenes.Zones[0].Devices[1].Status[0].Outputs[0].Value); Assert.Equal(21.6404131546947d, zonesScenes.Zones[0].Devices[1].Status[0].Outputs[0].TargetValue); Assert.Empty(zonesScenes.Zones[0].Devices[2].Status); }
public async Task TestGetTemperatureControlConfig() { var mockHttp = new MockHttpMessageHandler(); mockHttp.When($"{MockDigitalstromConnection.BaseUri}/json/apartment/getTemperatureControlConfig") .WithExactQueryString($"token={MockDigitalstromConnection.AppToken}") .Respond("application/json", @"{ ""result"": { ""zones"": [ { ""id"": 1, ""name"": ""RoomWithoutControl"", ""ControlMode"": 0 }, { ""id"": 32001, ""name"": ""RoomFollowing"", ""ControlMode"": 2, ""ReferenceZone"": 32027, ""CtrlOffset"": 0 }, { ""id"": 32027, ""name"": ""RoomWithControl"", ""ControlMode"": 1, ""EmergencyValue"": 75, ""CtrlKp"": 5, ""CtrlTs"": 1, ""CtrlTi"": 240, ""CtrlKd"": 0, ""CtrlImin"": -13.325000000000001, ""CtrlImax"": 13.325000000000001, ""CtrlYmin"": 0, ""CtrlYmax"": 100, ""CtrlAntiWindUp"": true } ] }, ""ok"": true }"); using var dsApiClient = new DigitalstromDssClient(mockHttp.AddAuthMock().ToMockProvider()); var result = await dsApiClient.GetTemperatureControlConfig(); Assert.Equal(0, result.Zones[0].ControlMode); Assert.Null(result.Zones[0].ReferenceZone); Assert.Null(result.Zones[0].CtrlOffset); Assert.Equal(2, result.Zones[1].ControlMode); Assert.Equal(32027, result.Zones[1].ReferenceZone); Assert.Equal(0, result.Zones[1].CtrlOffset); Assert.Null(result.Zones[1].CtrlKp); Assert.Equal(32027, (int)result.Zones[2].Id); Assert.Equal(1, result.Zones[2].ControlMode); Assert.Equal(75, result.Zones[2].EmergencyValue); Assert.Equal(5, result.Zones[2].CtrlKp); Assert.Equal(1, result.Zones[2].CtrlTs); Assert.Equal(240, result.Zones[2].CtrlTi); Assert.Null(result.Zones[2].ReferenceZone); }