[hdpowerview] Add support for scene groups (#11534)

* Add support for scene collections.

Fixes #11533

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Add unit test for parsing of scene collections response.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Add default i18n properties file.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix CAT: File does not end with a newline.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Update documentation with scene collections.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix CAT: File does not end with a newline.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix formatting.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix CAT: File does not end with a newline.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Split offline tests into separate distinct tests.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Increase test coverage for scene/scene collection parsing.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Internationalization of dynamic scene/scene collection channels.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Rename scene collections to scene groups.

Renamed for all user-oriented texts/references to be consistent with now abandoned feature of the PowerView app.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Change custom text keys to not collide with framework.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Avoid multiple thing updates.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Add missing label/description texts for secondary channel.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Remove unneeded @Nullable annotations.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
jlaur
2021-11-15 23:53:23 +01:00
committed by GitHub
parent 2973f6d890
commit 8c83c27c57
12 changed files with 420 additions and 96 deletions

View File

@@ -16,11 +16,12 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.openhab.binding.hdpowerview.internal.api.ActuatorClass.*;
import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -31,6 +32,8 @@ import org.openhab.binding.hdpowerview.internal.HubMaintenanceException;
import org.openhab.binding.hdpowerview.internal.HubProcessingException;
import org.openhab.binding.hdpowerview.internal.api.CoordinateSystem;
import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections;
import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
import org.openhab.binding.hdpowerview.internal.api.responses.Shade;
@@ -47,6 +50,7 @@ import com.google.gson.JsonParseException;
* Unit tests for HD PowerView binding
*
* @author Andrew Fiddian-Green - Initial contribution
* @author Jacob Laursen - Add support for scene groups
*/
@NonNullByDefault
public class HDPowerViewJUnitTests {
@@ -58,14 +62,9 @@ public class HDPowerViewJUnitTests {
* load a test JSON string from a file
*/
private String loadJson(String fileName) {
try (FileReader file = new FileReader(String.format("src/test/resources/%s.json", fileName));
BufferedReader reader = new BufferedReader(file)) {
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line).append("\n");
}
return builder.toString();
try {
return Files.readAllLines(Paths.get(String.format("src/test/resources/%s.json", fileName))).stream()
.collect(Collectors.joining());
} catch (IOException e) {
fail(e.getMessage());
}
@@ -287,80 +286,107 @@ public class HDPowerViewJUnitTests {
}
/**
* Run a series of OFFLINE tests on the JSON parsing machinery
* Test generic JSON shades response
*/
@Test
public void testOfflineJsonParsing() {
public void shadeResponseIsParsedCorrectly() throws JsonParseException {
final Gson gson = new Gson();
@Nullable
Shades shades;
// test generic JSON shades response
try {
@Nullable
String json = loadJson("shades");
assertNotNull(json);
assertNotEquals("", json);
shades = gson.fromJson(json, Shades.class);
assertNotNull(shades);
} catch (JsonParseException e) {
fail(e.getMessage());
}
String json = loadJson("shades");
assertNotEquals("", json);
shades = gson.fromJson(json, Shades.class);
assertNotNull(shades);
}
// test generic JSON scenes response
try {
@Nullable
String json = loadJson("scenes");
assertNotNull(json);
assertNotEquals("", json);
@Nullable
Scenes scenes = gson.fromJson(json, Scenes.class);
assertNotNull(scenes);
} catch (JsonParseException e) {
fail(e.getMessage());
}
/**
* Test generic JSON scene response
*/
@Test
public void sceneResponseIsParsedCorrectly() throws JsonParseException {
final Gson gson = new Gson();
String json = loadJson("scenes");
assertNotEquals("", json);
// test the JSON parsing for a duette top down bottom up shade
try {
@Nullable
ShadeData shadeData = null;
String json = loadJson("duette");
assertNotNull(json);
assertNotEquals("", json);
@Nullable
Scenes scenes = gson.fromJson(json, Scenes.class);
assertNotNull(scenes);
shades = gson.fromJson(json, Shades.class);
assertNotNull(shades);
@Nullable
List<ShadeData> shadesData = shades.shadeData;
assertNotNull(shadesData);
@Nullable
List<Scene> sceneData = scenes.sceneData;
assertNotNull(sceneData);
assertEquals(1, shadesData.size());
shadeData = shadesData.get(0);
assertNotNull(shadeData);
assertEquals(4, sceneData.size());
@Nullable
Scene scene = sceneData.get(0);
assertEquals("Door Open", scene.getName());
assertEquals(18097, scene.id);
}
assertEquals("Gardin 1", shadeData.getName());
assertEquals(63778, shadeData.id);
/**
* Test generic JSON scene collection response
*/
@Test
public void sceneCollectionResponseIsParsedCorrectly() throws JsonParseException {
final Gson gson = new Gson();
String json = loadJson("sceneCollections");
assertNotEquals("", json);
ShadePosition shadePos = shadeData.positions;
assertNotNull(shadePos);
assertEquals(ZERO_IS_CLOSED, shadePos.getCoordinateSystem(PRIMARY_ACTUATOR));
@Nullable
SceneCollections sceneCollections = gson.fromJson(json, SceneCollections.class);
assertNotNull(sceneCollections);
@Nullable
List<SceneCollection> sceneCollectionData = sceneCollections.sceneCollectionData;
assertNotNull(sceneCollectionData);
State pos = shadePos.getState(PRIMARY_ACTUATOR, ZERO_IS_CLOSED);
assertEquals(PercentType.class, pos.getClass());
assertEquals(59, ((PercentType) pos).intValue());
assertEquals(1, sceneCollectionData.size());
@Nullable
SceneCollection sceneCollection = sceneCollectionData.get(0);
assertEquals("Børn op", sceneCollection.getName());
assertEquals(27119, sceneCollection.id);
}
pos = shadePos.getState(SECONDARY_ACTUATOR, ZERO_IS_OPEN);
assertEquals(PercentType.class, pos.getClass());
assertEquals(35, ((PercentType) pos).intValue());
/**
* Test the JSON parsing for a duette top down bottom up shade
*/
@Test
public void duetteTopDownBottomUpShadeIsParsedCorrectly() throws JsonParseException {
final Gson gson = new Gson();
String json = loadJson("duette");
assertNotEquals("", json);
pos = shadePos.getState(PRIMARY_ACTUATOR, VANE_COORDS);
assertEquals(UnDefType.class, pos.getClass());
@Nullable
Shades shades = gson.fromJson(json, Shades.class);
assertNotNull(shades);
@Nullable
List<ShadeData> shadesData = shades.shadeData;
assertNotNull(shadesData);
assertEquals(3, shadeData.batteryStatus);
assertEquals(1, shadesData.size());
@Nullable
ShadeData shadeData = shadesData.get(0);
assertNotNull(shadeData);
assertEquals(4, shadeData.signalStrength);
} catch (JsonParseException e) {
fail(e.getMessage());
}
assertEquals("Gardin 1", shadeData.getName());
assertEquals(63778, shadeData.id);
ShadePosition shadePos = shadeData.positions;
assertNotNull(shadePos);
assertEquals(ZERO_IS_CLOSED, shadePos.getCoordinateSystem(PRIMARY_ACTUATOR));
State pos = shadePos.getState(PRIMARY_ACTUATOR, ZERO_IS_CLOSED);
assertEquals(PercentType.class, pos.getClass());
assertEquals(59, ((PercentType) pos).intValue());
pos = shadePos.getState(SECONDARY_ACTUATOR, ZERO_IS_OPEN);
assertEquals(PercentType.class, pos.getClass());
assertEquals(35, ((PercentType) pos).intValue());
pos = shadePos.getState(PRIMARY_ACTUATOR, VANE_COORDS);
assertEquals(UnDefType.class, pos.getClass());
assertEquals(3, shadeData.batteryStatus);
assertEquals(4, shadeData.signalStrength);
}
}

View File

@@ -0,0 +1,15 @@
{
"sceneCollectionIds": [
27119
],
"sceneCollectionData": [
{
"name": "QsO4cm4gb3A=",
"colorId": 12,
"iconId": 17,
"id": 27119,
"order": 0,
"hkAssist": false
}
]
}